标签:
Time Limit: 3000MS | Memory Limit: 30000K | |
Total Submissions: 22440 | Accepted: 5950 |
Description
Input
Output
Sample Input
1 3 3 1 2 3 1 3 4 2 3 5
Sample Output
Scenario #1: 4
这题对我来说太经典了,估计我整个ICPC生涯都不会忘了这题。因为做过类似的题,所以刚开始就推出了转移方程,即D[i]保存以i为终点的所有路径上最小载重值最大的点,更新方程就是if D[i] < min(D[s],COST[s][i]) then D[i] = min(D[i] + COST[s][i]).我用dijkstra来做,但是WA了,无奈上网看了看,发现方程是对的,于是又用bellman写了一遍,果然A了。于是我就怀疑是不是我dijkstra理解搓了,果断找出MIT的公开课又学了一遍,发现理解是对的,顺便学会了对S的证明,此题可证出加入S的点已经正确。然后就开始了为期两天的DEBUG工程,调得快崩溃了,证了无数遍改了无数遍,终于在今天跑出了一组错误的数据。最后发现,问题出在优先队列上。
我优先队列里保存的是顶点的编号,然后通过比较D值来维护。于是,就在这里,出现了一个惊天地泣鬼神的错误。如果顶点2被加入到了队列里,并且此时的D值等于10,那么当它后来再次被更新以后,比如D值更新到了8,此时再次push的话,是push不进去的!队列会认为此元素已经存在,所以不做任何反应,虽然它的键值已经改变!网上一查果然有人遇到了同样的问题,他描述的比我清楚,传送门http://bbs.byr.cn/#!article/ACM_ICPC/8739?p=1 ,里面的第二个例子。我后来采用了3楼的办法,同时保存顶点号与D值,这样即使顶点号相同,但D值不同的话依然可以入队。
顺便一说,前面几题我用的是保存顶点的方法,所以虽然A了但是其实是错的。
印象实在太深了,这是我调试得最深入的一题,记录留念!
1 #include <iostream> 2 #include <cstdio> 3 #include <queue> 4 #include <vector> 5 using namespace std; 6 7 const int INF = 0x6fffffff; 8 const int SIZE = 1005; 9 int N; 10 int D[SIZE]; 11 bool S[SIZE]; 12 13 struct NNode 14 { 15 int pos,dis; 16 bool operator <(const NNode & r) const 17 { 18 return dis < r.dis; 19 }; 20 }; 21 struct Node 22 { 23 int vec,cost; 24 }; 25 vector<Node> G[SIZE]; 26 27 void Dijkstra(int); 28 int main(void) 29 { 30 //freopen("out.txt","r",stdin); 31 //freopen("2.txt","w",stdout); 32 int n,m,from; 33 int count = 0; 34 Node temp; 35 36 scanf("%d",&n); 37 while(n --) 38 { 39 scanf("%d%d",&N,&m); 40 for(int i = 1;i <= N;i ++) 41 G[i].clear(); 42 while(m --) 43 { 44 scanf("%d%d%d",&from,&temp.vec,&temp.cost); 45 G[from].push_back(temp); 46 swap(from,temp.vec); 47 G[from].push_back(temp); 48 } 49 Dijkstra(1); 50 printf("Scenario #%d:\n",++ count); 51 printf("%d\n\n",D[N]); 52 53 } 54 55 return 0; 56 } 57 58 void Dijkstra(int s) 59 { 60 NNode temp; 61 62 priority_queue<NNode> que; 63 fill(S,S + SIZE,false); 64 fill(D,D + SIZE,0); 65 D[s] = INF; 66 temp.pos = s; 67 temp.dis = INF; 68 que.push(temp); 69 70 while(!que.empty()) 71 { 72 NNode cur = que.top(); 73 que.pop(); 74 S[cur.pos] = true; 75 if(cur.pos == N) 76 break; 77 78 for(int i = 0;i < G[cur.pos].size();i ++) 79 if(!S[G[cur.pos][i].vec] && D[G[cur.pos][i].vec] < min(D[cur.pos],G[cur.pos][i].cost)) 80 { 81 D[G[cur.pos][i].vec] = min(D[cur.pos],G[cur.pos][i].cost); 82 temp.pos = G[cur.pos][i].vec; 83 temp.dis = D[G[cur.pos][i].vec]; 84 que.push(temp); //如果只保存顶点号的话会出错 85 } 86 } 87 }
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 const int INF = 0x6fffffff; 6 const int SIZE = 1005; 7 struct Node 8 { 9 int from,to,cost; 10 }G[SIZE * SIZE]; 11 int N,M; 12 int D[SIZE]; 13 14 void Bellman_ford(int); 15 int main(void) 16 { 17 int n,m; 18 int count = 0; 19 20 scanf("%d",&n); 21 while(n --) 22 { 23 scanf("%d%d",&N,&M); 24 int temp = M; 25 int i = 0; 26 while(temp --) 27 { 28 scanf("%d%d%d",&G[i].from,&G[i].to,&G[i].cost); 29 i ++; 30 G[i].from = G[i - 1].to; 31 G[i].to = G[i - 1].from; 32 G[i].cost = G[i - 1].cost; 33 i ++; 34 } 35 Bellman_ford(1); 36 printf("Scenario #%d:\n",++ count); 37 printf("%d\n\n",D[N]); 38 } 39 40 return 0; 41 } 42 43 void Bellman_ford(int s) 44 { 45 fill(D,D + SIZE,0); 46 D[s] = INF; 47 for(int j = 0;j < N - 1;j ++) 48 { 49 bool update = false; 50 for(int i = 0;i < M * 2;i ++) 51 if(D[G[i].to] < min(D[G[i].from],G[i].cost)) 52 { 53 D[G[i].to] = min(D[G[i].from],G[i].cost); 54 update = true; 55 } 56 if(!update) 57 break; 58 } 59 }
POJ 1797 Heavy Transportation (最短路)
标签:
原文地址:http://www.cnblogs.com/xz816111/p/4507859.html