Tyvj 1221 微子危机——战略
背景
№.3
Summer联盟战前兵力战略转移。
描述
Summer的兵力分布在各个星球上,现在需要把他们全部转移到某个星球上。
Summer一共拥有N个星球(1~N),你要把这N个星球上的兵力转到第M个星球上。本来每个星球之间都有星际轨道连接,但Guiolk监视了某些轨道,我们一但走上这些轨道,有可能受到他的攻击。为了安全,Summer不会走被监视的轨道。于是,只有L个星际轨道是被批准通过的。Summer的国防部想统计一下所需的最短路程(即每个星球到第M星球的最短路程总和,单位:M PS:‘M‘不是米)。
输入格式
第一行有三个正整数,N,M,L(分别如题目描述)接下来L行,为被批准通行的轨道。每行有三个整数:a,b,c,表示第a个星球和第b个星球之间的轨道长cM(有重复)。
输出格式
如果所有星球上的兵力能全部集中到第M个星球,则输出: 最短路程和+“ M(s) are needed.”如果某个星球的兵力不能到达第M个星球,则输出“Sth wrong.”。
测试样例1
输入
【样例输入1】
5 3 6
1 2 1
1 3 3
2 3 1
4 1 5
4 5 2
5 1 2
【样例输入2】
5 3 4
1 2 1
1 3 3
2 3 1
5 1 2
输出
【样例输出1】
13 M(s) are needed.
【样例输出2】
Sth wrong.
备注
对于30%的数据,1≤N≤20 , L≤200
对于80%的数据,1≤N≤600 , L≤180000
对于100%的数据,1≤N≤1000 , 1≤M≤N , L≤500000, 1≤a,b≤N , 0≤c≤10000。
2010年广州市第二中学初二第二次测试第三题。
思路:
堆优化dij裸求最短路
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<vector> 6 #include<queue> 7 #include<algorithm> 8 #define mx 1001 9 10 using namespace std; 11 struct orz 12 { 13 int d,p; 14 friend bool operator <(orz a,orz b) {return a.d>b.d;}//堆和set里面都只有小于号,所以要用小根堆的话要将<重定向为> 15 }; 16 struct Edge{ 17 int to; 18 int w; 19 }; 20 priority_queue < orz > ss; 21 int flag = 0,v[mx],d[mx],n,m,l; 22 vector<Edge> edge[mx]; 23 void input(){ 24 cin>>n>>m>>l; 25 int u,v,wei; 26 Edge test; 27 for(int i = 1;i <= l;i++){ 28 scanf("%d%d%d",&u,&v,&wei); 29 test.to = v; 30 test.w = wei; 31 edge[u].push_back(test); 32 test.to = u; 33 edge[v].push_back(test); 34 } 35 for(int i = 0;i < mx;i++) d[i] = 1000000000; 36 } 37 void dij(int s) 38 { 39 40 d[s]=0; 41 orz tmp; 42 tmp.d=0,tmp.p=s; 43 ss.push(tmp); 44 flag++; 45 int x,dd; 46 Edge j; 47 while (!ss.empty())//不能只做n次,要一直做到堆空 48 { 49 tmp=ss.top(); 50 ss.pop(); 51 x=tmp.p,dd=tmp.d; 52 if (v[x]==flag) continue;//这里一定要判断!!! 53 v[x]=flag; 54 for (int i = 0;i < edge[x].size();i++){ 55 56 j = edge[x][i]; 57 if (d[j.to]>dd+j.w) 58 { 59 d[j.to]=dd+j.w; 60 tmp.d=dd+j.w,tmp.p=j.to; 61 ss.push(tmp); 62 } 63 } 64 65 } 66 } 67 int main(){ 68 input(); 69 dij(m); 70 int ans = 0; 71 for(int i = 1;i <= n;i++){ 72 if(i == m) continue; 73 if(d[i] >= 1000000000){ 74 cout<<"Sth wrong."<<endl; 75 return 0; 76 } 77 ans+=d[i]; 78 } 79 cout<<ans<<" M(s) are needed."<<endl; 80 return 0; 81 }
Tyvj 1176 火焰巨魔的惆怅
背景
TYVJ2月月赛第一道
巨魔家族在某天受到了其他种族的屠杀,作为一个英雄,他主动担任了断后的任务,但是,在巨魔家族整体转移过后,火焰巨魔却被困住了,他出逃的方式也只有召唤小火人这一种方式,所以请你帮助他。
描述
我们把火焰巨魔所处的位置抽象成一张有向图,他的位置就是1号点位,目的就是走到第N号点位,因为小火人会裂嘛,所以我们可以看做每走一条路,小火人的数量都会加倍,而每条路上的敌人有多强,会消耗多少小火人c[i]也会给出(c[i]为负值);当然有些时候路上也会遇到魔法泉之类的东西,这时候就可以补充一些小火人咯(c[i]为正值)。如果小火人死光了,那么火焰巨魔也就可以看做是挂了,毕竟智力型英雄就是脆啊。希望你帮助火焰巨魔用最少的初始小火人逃离这次屠杀。
输入格式
第一行两个数N(<=50000),M(<=100000)表示点位数与边数。
一下M行,每行三个数a,b,c表示a,b两点间的边权是c(|c|<=10000)
输出格式
输出仅一个整数,表示最小初始小火人数。
测试样例1
输入
5 4
1 2 -3
1 3 -6
3 4 1
4 5 -9
输出
4
备注
初始小火人为4个,到3点剩2个,到4变成5个,到5剩1个。
所以初始最少为4,更少的小火人是不足以走到5号点位的。from wsd TYVJ月赛出题组
思路:
1、由于要求的是从起点到达终点最少出发的小火人,所以是一个路径寻找问题,所以要用到最短路
2、由于小火人最少是1,所以到终点后小火人数量一定是1,否则就必须要在起点派出更多小火人
3、在最短路中,目的是求长度最小,放入队列的必要条件是可以把该点长度变小,所以此题中放入的条件是可以把所需要的火人数量变小
4、从终点开始,做spfa,则由用来松弛的点走到当前节点的最小火人数设为x,则2x + g[now][i] = d[now],可知x可能不为正整数,若为浮点数则向上取整,若x≤0,则将x设为1,然后去比较d[i]进行松弛,最后d[1]便是正确答案
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<algorithm> 6 #include<vector> 7 #include<queue> 8 using namespace std; 9 const int maxn = 100005; 10 const int maxint = ~0U>>1; 11 struct edge{ 12 int v; 13 int w; 14 }; 15 int n,m,vis[maxn],d[maxn]; 16 vector<edge> g[maxn]; 17 void input(){ 18 cin>>n>>m; 19 int u,v,w; 20 edge tmp; 21 for(int i = 1;i <= m;i++){ 22 scanf("%d%d%d",&u,&v,&w); 23 tmp.v = u; 24 tmp.w = w; 25 g[v].push_back(tmp); 26 } 27 for(int i = 1;i <= n;i++){ 28 vis[i] = 0; 29 d[i] = maxint; 30 } 31 } 32 void spfa(){ 33 queue<int> q; 34 q.push(n); 35 d[n] = 1; 36 vis[n] = 1; 37 int now,to,add; 38 while(!q.empty()){ 39 now = q.front(); 40 q.pop(); 41 vis[now] = 0; 42 for(int i = 0;i < g[now].size();i++){ 43 to = g[now][i].v; 44 add = (d[now] - g[now][i].w) >> 1; 45 if((d[now]-g[now][i].w) & 1) add++; 46 if(add <= 0) add = 1; 47 if(d[to] > add){ 48 d[to] = add; 49 if(!vis[to]){ 50 vis[to] = 1; 51 q.push(to); 52 } 53 } 54 } 55 } 56 } 57 int main(){ 58 input(); 59 spfa(); 60 cout<<d[1]; 61 return 0; 62 }