1. 程式人生 > >Bellman-Ford演算法模板

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;
}