Bellman-Ford算法模板

Bellman-Ford算法最重要的一个应用是判负环。


在迭代n-1次后如果还可以进行松弛操作,说明一定存在负圈。


如果包含负环,则路径不存在。


以下为SPFA优化模板:

#include<iostream>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<cstdlib>
#define inf 0x3f3f3f3f
#define LL long long
using namespace std;
struct Edge
{
    int from,to,dist;
};
vector<Edge> edges;
vector<int> g[1005];//存储from对应的边的标号
bool inq[1005];//是否在队列中
int d[1005];//源点到各个点的最短路
int pre[1005];//最短路的上一条弧
int cnt[1005];//进队次数
int n,m;//n点的个数,m边的个数
int a,b;//求a到b的最短路径并输出a到b的路径
void init()
{
    for(int i=0;i<=n-1;i++)
        g[i].clear();
    edges.clear();
}
void addedge(int from,int to,int dist)//边从0开始
{
    edges.push_back((Edge){from,to,dist});
    int num=edges.size();
    g[from].push_back(num-1);
}
bool spfa(int s)//若存在负环返回false
{
    queue<int> q;
    memset(inq,0,sizeof(inq));
    memset(cnt,0,sizeof(cnt));
    memset(d,0x3f,sizeof(d));
    d[s]=0;
    inq[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        inq[u]=0;
        for(int i=0;i<g[u].size();i++)
        {
            Edge e=edges[g[u][i]];
            if(d[e.to]>d[u]+e.dist)
            {
                d[e.to]=d[u]+e.dist;
                pre[e.to]=g[u][i];
                if(!inq[e.to])
                {
                    q.push(e.to);
                    inq[e.to]=1;
                    if(++cnt[e.to]>n)
                        return false;//有负环
                }
            }
        }
    }
    return true;
}
void print(int s)//输出源点a到s的最短路径
{
    if(s==a)
        return ;
    print(edges[pre[s]].from);
    cout<<edges[pre[s]].from<<" ";
}
int main()
{
    cin>>n>>m;
    init();
    for(int i=0;i<=m-1;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        addedge(a,b,c);
    }
    cin>>a>>b;//求a到b最短路
    if(spfa(a))
    {
        cout<<d[b]<<endl;
        print(b);
        cout<<b<<endl;
    }
    else
        cout<<-1<<endl;
    return 0;
}


你可能感兴趣的:(Bellman-Ford算法)