1.初始化:s为源点时d[s]=0,d[x]=inf(x!=s)【inf是正无穷大】
2.迭代n-1次后还能继续松弛,说明存在负环
并且在第n次更新中可以通过断点找出回路(n为顶点数量)
3.对于有向图,松弛操作只需要松弛一条边的一端
无向图两边同时松弛!
注意!!无向图的松弛操作比有向图多出一个端点
松弛的原则是:u->v这条边,用dis[u]推导dis[v]的值
下面我们以HDU2544的最短路题目为例,附上代码以供参考
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=105;
const int maxm=10005;
int n,m,a,b,t;
int v[maxm],u[maxm];//保存边两条连接的顶点序号
int w[maxm];//保存边的权值
int dis[maxn];//保存最短路径结果
void init()
{
memset(v,-1,sizeof(v));
memset(u,-1,sizeof(u));
memset(w,inf,sizeof(w));
memset(dis,inf,sizeof(dis));
dis[1]=0;
}
void bellman_ford()
{
for(int i=0; i<n-1; i++) //对所有边更新n-1次
{
int flag=1;//如果在当前一轮中没有松弛,说明全部结点都达到最短路径,跳出循环即可
for(int j=0; j<m; j++)
if(dis[u[j]]>dis[v[j]]+w[j])
{
dis[u[j]]=dis[v[j]]+w[j];
flag=0;
}
for(int j=0; j<m; j++)
if(dis[v[j]]>dis[u[j]]+w[j])
{
dis[v[j]]=dis[u[j]]+w[j];
flag=0;
}
if(flag)
break;
}
}
int main()
{
while(scanf("%d%d",&n,&m),n+m)
{
init();
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&a,&b,&t);
u[i]=a;
v[i]=b;
w[i]=t;
}
bellman_ford();
printf("%d\n",dis[n]);
}
return 0;
}