poj3259_bellman-ford
题意:famer给出一些fields,paths,wormholes.其中paths是fields之间的双向正权值边,wormholes是fields之间的单向负权边。求在这个图中是否存在权值为负的回路。
这个题用的是bellman_ford算法。其中有一下几个问题:
1.在描述Paths时,a bidirectional path between S and E that requires T seconds to traverse. Two fields might be connected by more than one path. 当时没有看到是双向边,WA了。还有,我没有对后半句处理,也过了。
2.一开始以第一个点为源点进行bellman-ford,结果WA了。后来发现,bellman-ford可以得出是否存在着一个从源点可达的权为负的回路。而本题是要求在图中是否存在环。因此需要对未处理过的点进行遍历进行bellman-ford。或者是看到网上有种做法是,初始化每个节点的d值为0或者某一个数这样也可以判断图中是否存在某个负权的环。这种做法类似差分约束引入顶点v0,保证从v0可到每个顶点。权值为0,直接赋给d[i]就可以了
3.一点小的优化,bellman-ford中进行n-1次遍历的时候可以设置标志flag,如果某次遍历中flag没有变化的时候,就可以终止。跟冒泡排序的思想一样。
代码:
View Code
1 #include <iostream> 2 #include <stdio.h> 3 using namespace std; 4 const int maxe=5210; 5 const int maxp=505; 6 const int maxnum=10005; 7 int p,m,w; 8 struct edge 9 { 10 int v; 11 int w; 12 int next; 13 }edge[maxe]; 14 15 typedef struct 16 { 17 int d; 18 int pre; 19 }pp; 20 pp point[maxp]; 21 22 void Init() 23 { 24 int i; 25 for(i=1;i<=p;i++) 26 { 27 point[i].d=0; //全都置为0 28 point[i].pre=-1; 29 } 30 int u,v,weight; 31 int index=1; 32 for(i=1;i<=m;i++) 33 { 34 scanf("%d%d%d",&u,&v,&weight); 35 edge[index].v=v; 36 edge[index].w=weight; 37 edge[index].next=point[u].pre; 38 point[u].pre=index; 39 index++; 40 41 edge[index].v=u; 42 edge[index].w=weight; 43 edge[index].next=point[v].pre; 44 point[v].pre=index; 45 index++; 46 } 47 for(i=1;i<=w;i++) 48 { 49 scanf("%d%d%d",&u,&v,&weight); 50 edge[index].v=v; 51 edge[index].w=-1*weight; 52 edge[index].next=point[u].pre; 53 point[u].pre=index; 54 index++; 55 } 56 } 57 58 void traversal() 59 { 60 int i,j; 61 for(i=1;i<=p;i++) 62 for(j=point[i].pre;j!=-1;j=edge[j].next) 63 cout<<i<<" "<<edge[j].v<<" "<<edge[j].w<<endl; 64 } 65 66 bool bellman_ford() 67 { 68 int i,j,k; 69 bool flag; 70 for(k=1;k<=p-1;k++) 71 { 72 flag=false; 73 for(i=1;i<=p;i++) 74 for(j=point[i].pre;j!=-1;j=edge[j].next) 75 { 76 int v,w; 77 v=edge[j].v; 78 w=edge[j].w; 79 if(point[i].d==maxnum) continue; 80 else if(point[v].d>point[i].d+w) 81 { 82 point[v].d=point[i].d+w; 83 flag=true; 84 } 85 } 86 if(!flag) 87 break; 88 } 89 90 for(i=1;i<=p;i++) 91 for(j=point[i].pre;j!=-1;j=edge[j].next) 92 if(point[edge[j].v].d>point[i].d+edge[j].w) 93 return false; 94 return true; 95 } 96 97 int main() 98 { 99 int num; 100 bool flag; 101 scanf("%d",&num); 102 while(num--) 103 { 104 scanf("%d%d%d",&p,&m,&w); 105 Init(); 106 //cout<<endl; 107 //traversal(); 108 //point[1].d=0; 109 flag=bellman_ford(); 110 if(flag) 111 printf("NO\n"); 112 else 113 printf("YES\n"); 114 } 115 return 0; 116 }
tju oj 2831
下面是遍历的做法,但不知道为什么不过?
View Code
1 #include <iostream> 2 #include <stdio.h> 3 #define white 0 4 #define black 1 5 using namespace std; 6 const int maxe=5210; 7 const int maxp=505; 8 const int maxnum=10005; 9 int p,m,w; 10 struct edge 11 { 12 int v; 13 int w; 14 int next; 15 }edge[maxe]; 16 17 typedef struct 18 { 19 int d; 20 int color; 21 int pre; 22 }pp; 23 pp point[maxp]; 24 bool f; 25 26 void Init() 27 { 28 int i; 29 for(i=1;i<=p;i++) 30 { 31 point[i].d=maxnum; //全都置为0 32 point[i].pre=-1; 33 point[i].color=white; 34 } 35 int u,v,weight; 36 int index=1; 37 for(i=1;i<=m;i++) 38 { 39 scanf("%d%d%d",&u,&v,&weight); 40 edge[index].v=v; 41 edge[index].w=weight; 42 edge[index].next=point[u].pre; 43 point[u].pre=index; 44 index++; 45 46 edge[index].v=u; 47 edge[index].w=weight; 48 edge[index].next=point[v].pre; 49 point[v].pre=index; 50 index++; 51 } 52 for(i=1;i<=w;i++) 53 { 54 scanf("%d%d%d",&u,&v,&weight); 55 edge[index].v=v; 56 edge[index].w=-1*weight; 57 edge[index].next=point[u].pre; 58 point[u].pre=index; 59 index++; 60 } 61 } 62 63 void traversal() 64 { 65 int i,j; 66 for(i=1;i<=p;i++) 67 for(j=point[i].pre;j!=-1;j=edge[j].next) 68 cout<<i<<" "<<edge[j].v<<" "<<edge[j].w<<endl; 69 } 70 71 void bellman_ford(int u) 72 { 73 point[u].d=0; 74 point[u].color=black; 75 int i,j,k; 76 bool flag; 77 for(k=1;k<=p-1;k++) 78 { 79 flag=false; 80 for(i=1;i<=p;i++) 81 for(j=point[i].pre;j!=-1;j=edge[j].next) 82 { 83 int v,w; 84 v=edge[j].v; 85 point[v].color=black; 86 w=edge[j].w; 87 if(point[i].d==maxnum) continue; 88 else if(point[v].d>point[i].d+w) 89 { 90 point[v].d=point[i].d+w; 91 flag=true; 92 } 93 } 94 if(!flag) 95 break; 96 } 97 98 for(i=1;i<=p;i++) 99 for(j=point[i].pre;j!=-1;j=edge[j].next) 100 if(point[edge[j].v].d>point[i].d+edge[j].w) 101 { 102 f=false; 103 return ; 104 } 105 f=true; 106 } 107 108 int main() 109 { 110 int num,i; 111 scanf("%d",&num); 112 while(num--) 113 { 114 scanf("%d%d%d",&p,&m,&w); 115 Init(); 116 //cout<<endl; 117 //traversal(); 118 //point[1].d=0; 119 f=true; 120 for(i=1;i<=p;i++) 121 { 122 if(!f) break; 123 if(point[i].color==white) 124 bellman_ford(i); 125 } 126 if(f) 127 printf("NO\n"); 128 else 129 printf("YES\n"); 130 } 131 return 0; 132 }