Bellman-Ford------贝尔曼福特算法
我们之前学习了Dijkstra算法,用于计算单源,正边权的最短路径。
而今天学习的贝尔曼福特算法,是用于计算单源,且可含负边权的最短路径问题。其优于Dijkstra的方面是边的权值可以是负数,但还是那句话鱼和熊掌不可兼得啊,时间复杂度自然有点高。

| 1 | 2 | 3 | |
|---|---|---|---|
| 初始 | 0 | ∞\infty∞ | ∞\infty∞ |
| k=1 | 0 | 1 | 3 |
| k=2 | 0 | 1 | min(3,1+1)=2 |
我们首先初始值原点到1的最短距离为0,其余的都为∞\infty∞,接下来k=1,1到2的距离min(∞\infty∞,1的距离+W<1到2的边权>)结果为1,再从1到3的距离min(∞\infty∞,1的距离+W<1到3的边权>)结果为3,再到k=2,2的距离不变,看2到3的距离min(3,2的最短距离+W<2到3的边权>)结果为2。
其余的以此类推。。。
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
const int N=105,M=1005,INF=0x3f3f3f3f;
int dis[N];
int n,m;
struct Edge
{
int u,v,w;
}edge[M];
bool bellman(int s)
{
memset(dis,0x3f,sizeof(dis));
dis[s]=0;
for(int k=1;k<=n-1;k++)
{
bool vis1=false;
for(int i=0;i<m;i++)
{
int u=edge[i].u;
int v=edge[i].v;
int w=edge[i].w;
if(dis[u]!=INF&&dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
vis1=true;
}
}
if(!vis1) break;
}
//判断是否存在负环
for(int i=0;i<m;i++)
{
int u=edge[i].u;
int v=edge[i].v;
int w=edge[i].w;
if(dis[u]!=INF&&dis[v]>dis[u]+w)
{
return true;
}
}
return false;
}
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
{
int a,b,w;
cin>>a>>b>>w;
edge[i].u=a;
edge[i].v=b;
edge[i].w=w;
}
if(bellman(1))
{
cout<<"存在负环"<<endl;
}
else
{
for(int i=1;i<=n;i++)
{
if(dis[i]>=INF)
cout<<"-1"<<" ";
else
cout<<dis[i]<<" ";
}
}
return 0;
}
这个相较于Dijkstra,可以算负边,并且可以查看是否存在负环,但是复杂度有点高。