1. 程式人生 > 實用技巧 >bellman-ford演算法求K短路O(n*m),以及判負環O(n*m)

bellman-ford演算法求K短路O(n*m),以及判負環O(n*m)

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

const int N=510,M=1e4+10;

int n,m,k,dis[N],backup[N];
//dis陣列表示dis[i]到起點的距離。

struct 
{
    int a,b,w;
}edge[M];

//bellman-ford可以求出來圖中有沒有負權迴路。

//迭代k次返回的數表示:從起點經過不超過k條邊到各個點的最短距離

/*
bellman-ford可以判斷負環O(n*m),如果第n次迭代仍然有更新,則說明找到
了n條邊的最短路徑,如果一條最短路徑上有n條邊,
即有n+1個點,根據抽屜原理,說明有負環。

一般用spfa演算法判斷負環
*/
int bellman_ford()//直接返回k短路的距離,當k==m時返回起點到終點的最短距離
{
    memset(dis,0x3f,sizeof dis);
    dis[1]=0;
    
    for(int i=0;i<k;i++)//k次迭代,沒次迭代每次得到一個
    //到起點的最近的鄰居點。
    {
        //防止出現串聯的情況
        memcpy(backup,dis,sizeof dis);
        for(int j=0;j<m;j++)//列舉所有的m條邊
        {
            int a=edge[j].a,b=edge[j].b,w=edge[j].w;
            dis[b]=min(dis[b],backup[a]+w);
        }
    }
    
    if(dis[n]>0x3f3f3f3f/2)return -1;
        return dis[n];
    
}

int main()
{
    cin>>n>>m>>k;
    for(int i=0;i<m;i++)
    {
        scanf("%d%d%d",&edge[i].a,&edge[i].b,&edge[i].w);
    }
    int t=bellman_ford();
    if(t==-1)
    cout<<"impossible";
    else
    cout<<t;
    return 0;
}