题目描述:
有n个点,2m条正权路,w条负权路,求能不能从其中一个点进入,回到自己时走过的路径为负值。
解题思路:
归结为bellman-ford问题。bellman建立在求无负权值回路的最短路径问题上,如果在外层的第n次循环还有点值更新,就说明存在负权值回路,既不能收敛。——这个问题就是检查这个图是否存在负权值回路。
注意:普通路径是双向的!所以数组大小一定要开够。
代码:
#include <stdio.h>
#include <stdlib.h>
#define N 1001
#define M 6000
#define MAX 2000000000
typedef struct{
int s;
int e;
int t;
}Edge;
Edge edge[M];
int Farm[N][N], D[N];
int n,m,w;
int bellman_ford()
{
int i,j,f;
for(i=2;i<=n;i++)
{
f = 0;
for(j=1;j<=2*m+w;j++)
{
if(D[edge[j].s]<MAX && D[edge[j].e] > D[edge[j].s]+edge[j].t)
{
f = 1;
D[edge[j].e] = D[edge[j].s]+edge[j].t;
}
}
if(0 == f)
return 1;
}
for(j=1;j<=2*m+w;j++)
{
if(D[edge[j].s]<MAX && D[edge[j].e] > D[edge[j].s]+edge[j].t)
return 0;
}
return 1;
}
main()
{
int t,f,i;
scanf(“%d”,&t);
while(t>0)
{
scanf(“%d %d %d”,&n, &m, &w);
for(i=1;i<=2*m;i=i+2)
{
scanf(“%d %d %d”,&edge[i].s,&edge[i].e,&edge[i].t);
edge[i+1].s = edge[i].e;
edge[i+1].e = edge[i].s;
edge[i+1].t = edge[i].t;
}
for(i=2*m+1;i<=2*m+w;i++)
{
scanf(“%d %d %d”,&edge[i].s,&edge[i].e,&edge[i].t);
edge[i].t = 0 – edge[i].t;
}
for(i=1;i<=n;i++)
D[i] = MAX;
D[1] = 0;
f = bellman_ford();
if(1 == f)//没有负权回路
printf(“NO\n”);
else
printf(“YES\n”);
t–;
}
//system(“pause”);
return 0;
}