贝尔曼福特算法求单源最短路,主要是对每条边进行n-1次松弛操作,找到最短路
判断图中是否存在从源点可达的负权路:
遍历图中所有的边(eg(u,v)),若存在dis[v]>dis[u]+w(u,v)的情况,则存在权为负的回路。
<pre name="code" class="cpp">#include<stdio.h>
#include<string.h>
#define inf 1<<28
int dis[200];
struct node
{
int u,v,w;
}eg[22000];
void BF(int s,int t,int n,int m)
{
int i,j,flag;
//初始化
for(i=0;i<=n;i++)
dis[i]=inf;
dis[s]=0;
for(i=1;i<n;i++) //两点之间最多n-1条边可以将其相连
{ //所以循环n-1次
flag=0; //优化
for(j=0;j<m;j++)
{
if(dis[eg[j].v]>dis[eg[j].u]+eg[j].w)
{
dis[eg[j].v]=dis[eg[j].u]+eg[j].w; //松弛操作
flag=1; //松弛成功
}
}
if(!flag) //若没有松弛成功,跳出循环
break;
}
printf("%d\n",dis[t]==inf?-1:dis[t]);
}
int main()
{
int n,m,i,j;
int a,b,c;
while(scanf("%d%d",&n,&m),n||m)
{
int cont=0;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
//无向图,cont记录总共的边数
eg[cont].u=a;
eg[cont].v=b;
eg[cont++].w=c;
eg[cont].u=b;
eg[cont].v=a;
eg[cont++].w=c;
}
BF(1,n,n,cont);
}
return 0;
}
也可以用贝尔曼福特算法求最长路,把所有边变为负值,dis数组初始化为负无穷,求最小的,然后再取其正值即为所求。