POJ_3250_Wormholes(Bellman-Ford算法)
代码1:
/*
bellman-ford算法适合单源路径算法,和负权回路。
因此算法核心就是松弛操作
*/
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 bellman-ford算法适合单源路径算法,和负权回路。 3 */ 4 # include<stdio.h> 5 # include <string.h> 6 using namespace std; 7 int d[1001]; //源点到各点权值 8 int max_w=10001; //无穷远 9 struct node 10 { 11 int s; 12 int e; 13 int t; 14 }edge[5200]; 15 int N,M,W_h; 16 int all_e; //所有的边数。 17 bool bellman() 18 { 19 bool flag; 20 for(int i=0;i<N-1;i++) //为什么是N-1,因为对于N个结点的图最多有N-1个结点可能对其执行松弛操作。 21 { 22 flag=false; 23 for(int j=0;j<all_e;j++) 24 if(d[edge[j].e] > d[edge[j].s] + edge[j].t) 25 { 26 d[edge[j].e] = d[edge[j].s] + edge[j].t; 27 flag=true; //relax对路径有更新 28 } 29 if(!flag) 30 break; //只要某一次relax没有更新,说明最短路径已经查找完毕, 31 //或者部分点不可达,可以跳出循环(releax),或者直接返回false。 32 } 33 // if(!flag) 34 // return false; 35 for(int k=0;k<all_e;k++) //如果还能进行松弛操作,说明有负权回路。 36 if( dis[edge[k].e] > dis[edge[k].s] + edge[k].t) 37 return true; 38 return false; 39 } 40 int main(void) 41 { 42 int u,v,w; 43 int F; 44 cin>>F; 45 while(F--) 46 { 47 memset(dis,max_w,sizeof(dis)); //源点到各点的初始值为无穷,即默认不连通 48 cin>>N>>M>>W_h; 49 all_e=0; 50 //双向边赋值。 51 for(int i=1;i<=M;i++) 52 { 53 cin>>u>>v>>w; 54 edge[all_e].s=edge[all_e+1].e=u; 55 edge[all_e].e=edge[all_e+1].s=v; 56 edge[all_e++].t=w; 57 edge[all_e++].t=w; 58 } 59 //单向边赋值。 60 for(int j=1;j<=W_h;j++) 61 { 62 cin>>u>>v>>w; 63 edge[all_e].s=u; 64 edge[all_e].e=v; 65 edge[all_e++].t=-w; //注意权值为负 66 } 67 if(bellman()) 68 cout<<"YES"<<endl; 69 else 70 cout<<"NO"<<endl; 71 } 72 return 0; 73 }
代码二:
用上一题的思路
http://www.cnblogs.com/liun1994/articles/3257344.html
/*这里源点的时间用0来标记,那么在以后的操作中,我只要能找到那么一个回路能使得源点变成<0就说明能够穿越。*/
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 想不起来什么意思就画图看一下。 3 */ 4 # include <string.h> 5 #include<iostream> 6 using namespace std; 7 int dis[1001]; 8 int max_w=10001; 9 struct node 10 { 11 int s; 12 int e; 13 int t; 14 }edge[5200]; 15 int N,M,W_h; 16 int all_e; 17 18 bool bellman(void) 19 { 20 bool flag; 21 dis[1]=0; 22 while(dis[1] >= 0)//当找到比他小的时候就退出,说明肯定能够穿越 23 { 24 flag=false; 25 for(int j=0;j<all_e;j++) 26 if(dis[edge[j].e] > dis[edge[j].s] + edge[j].t) 27 { 28 dis[edge[j].e] = dis[edge[j].s] + edge[j].t; 29 flag=true; 30 } 31 if(!flag) //如果找一圈之后没有可以改变的了,说明已经找到头了,直接比较即可。 32 return dis[1]<0 ? 1:0; 33 } 34 return 1; 35 } 36 int main(void) 37 { 38 int u,v,w; 39 int F; 40 cin>>F; 41 while(F--) 42 { 43 memset(dis,1000000,sizeof(dis)); //源点到各点的初始值为无穷,即默认不连通 44 cin>>N>>M>>W_h; 45 all_e=0; 46 for(int i=1;i<=M;i++) 47 { 48 cin>>u>>v>>w; 49 edge[all_e].s=edge[all_e+1].e=u; 50 edge[all_e].e=edge[all_e+1].s=v; 51 edge[all_e++].t=w; 52 edge[all_e++].t=w; 53 } 54 for(int j=1;j<=W_h;j++) 55 { 56 cin>>u>>v>>w; 57 edge[all_e].s=u; 58 edge[all_e].e=v; 59 edge[all_e++].t=-w; 60 } 61 if(bellman()) 62 cout<<"YES"<<endl; 63 else 64 cout<<"NO"<<endl; 65 } 66 return 0; 67 }