题目链接: 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;
}