参考例题:AcWing.853有边数限制的最短路
ford算法的优势是可以限制最短路边数,并且可以检测负环且输出(SPFA算法无法输出负环).
ps:如果第n次迭代仍然会松弛三角不等式,就说明存在一条长度是n+1的最短路径,由抽屉原理,路径中至少存在两个相同的点,说明图中存在负权回路。
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int INF=0x3f3f3f3f;
const int mod=142857;
const int maxn=1e5+5;
ll n,m,k;ll d[maxn],backup[maxn];
struct node{
ll u,v,w;
}edge[maxn];
ll Bellman_ford(ll s){
memset(d,INF,sizeof(d));
d[s]=0;
for(ll i=1;i<=k;i++){
memcpy(backup,d,sizeof(d));
for(ll j=1;j<=m;j++){
ll u=edge[j].u,v=edge[j].v,w=edge[j].w;
if(backup[u]!=INF&&d[v]>backup[u]+w){
d[v]=backup[u]+w;
}
}
}
return d[n];
}
int main(){
cin>>n>>m>>k;
for(ll i=1;i<=m;i++){
ll u,v,w;
cin>>edge[i].u>>edge[i].v>>edge[i].w;
}
ll sum=Bellman_ford(1);
if(sum<INF/2) cout<<sum<<endl;
else puts("impossible");
}
Ford算法的路径打印:
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1e5+5;
ll n,m,s,e;ll d[maxn],backup[maxn];
ll path[maxn];
struct node{
ll u,v,w;
}edge[maxn];
void Bellman_ford(ll s){
memset(d,INF,sizeof(d));
memset(path,-1,sizeof(path));
d[s]=0;
for(ll i=1;i<=n;i++){
memcpy(backup,d,sizeof(d));
for(ll j=1;j<=m;j++){
ll u=edge[j].u,v=edge[j].v,w=edge[j].w;
if(backup[u]!=INF&&d[v]>backup[u]+w){
d[v]=backup[u]+w;
path[v]=u;
}
}
}
}
void print_path(ll s,ll e){
queue<ll> q;
ll x=e;
while(path[x]!=-1){
q.push(x);
x=path[x];
}
cout<<s;
while(!q.empty()){
cout<<"->"<<q.front();
q.pop();
}
cout<<endl;
}
int main(){
cin>>n>>m;
for(ll i=1;i<=m;i++){
ll u,v,w;
cin>>edge[i].u>>edge[i].v>>edge[i].w;
}
cin>>s>>e;//输入起点和终点
Bellman_ford(s);
if(d[e]<INF/2) print_path(s,e);
else puts("NO");
}
/*
3 3
1 2 5
2 3 -3
1 3 4
1 3
*/