题目链接: pku3259 Wormholes
之前在数据结构书上看了dijkstra 和floyed(从来没有自己写过)
但是有负权边的一直不会
所以专门找了题目看看怎么写
感觉上bellmanford 跟 dijkstra 处理问题的关键步骤差不多
都是不断的松弛
但是bellmanford顺序不同
dijkstra是对每个点进行松弛
bellmanford则是对每一条边进行松弛(实际上也是点,松弛有向线段的一个顶点)
//pku 3259 Wormholes //http://poj.org/problem?id=3259 //点数 N ∈ [1,500] ,边数 W ∈ [1,2500] ,虫洞数 W ∈ [1,200] //每条边取值范围 ∈ [-10000,10000] #include <stdio.h> #define INF 10001 #define M 3000 struct { int front,end,num; }edge[M*2+10]; //双向图 int dist[M] = {0},pre[M],i,j; bool bellman_ford(int n,int s,int e) //点数n 起点s 边数 {//调用bellman_ford( n, 1, e) for(i = 1;i <= n;i++) //初始化 { dist[i] = INF; // pre[i] = -1; } dist[s] = 0; //原点的最短距离初始化为0 for(i = 1;i <= n - 1;i++) //循环除起点s外的其他n-1个点 for(j = 1;j <= e;j++) //对每条边进行松弛操作 { if(dist[ edge[j].end ] > dist[ edge[j].front ] + edge[j].num) { dist [edge[j].end ] = dist[ edge[j].front ] + edge[j].num; // pre[ edge[j].end ] = edge[j].front; //pre记录每个结点的前导 } } for(i = 1;i <= e;i++) { if(dist[ edge[i].end ] > dist[ edge[i].front ] + edge[i].num) //成立则存在负环 return false; } return true; } int main() { int F,n,m,w,i,e,x,y,z; scanf("%d",&F); while(F--) { e = 1; scanf("%d%d%d",&n,&m,&w); //点数n 边数m 虫洞数w for(i = 1;i <= m;i++) { scanf("%d%d%d",&x,&y,&z); edge[e].front = x; //因为都是单向边 edge[e].end = y; edge[e++].num = z; edge[e].front = y; //所以要反着在来一次 edge[e].end = x; edge[e++].num = z; } for(i = 1;i <= w;i++) { scanf("%d%d%d",&x,&y,&z); edge[e].front = x; //接着之前的e给edge赋值 edge[e].end = y; edge[e++].num = z*-1; //负边 } if(! bellman_ford(n,1,e)) //若false printf("YES\n"); //存在负环 else printf("NO\n"); // for(i=1;i<=n;i++) // printf("dist[%d]=%d ",i,dist[i]); // printf("\n"); // for(i = 1;i <= e-1;i++) // printf("%d: dist[%d]=%d>dist[%d]=%d+cost=%d?\n",i,edge[i].end,dist[edge[i].end],edge[i].front,dist[edge[i].front],edge[i].num); // printf("\n"); } return 0; }