Johnson全源最短路

Grylls_117發表於2024-08-14

Johnson全源最短路

引入

對於一個無負環的圖,我們可以用Floyd或n遍Bellman-ford求出它的全源最短路
Floyd複雜度為O(\(n^3\))在稀疏圖上效率極低
n遍Bellman-ford O(\(n^2m\))效率遠不及 Floyd
注意到n遍dijstra複雜度為O(\(nm~log~m\))或O(\(n^3\))快於Floyd
但無法在負權圖上跑,考慮對邊進行重新賦值,使之為非負數

Johnson


注:最終答案\(dis_{i,j}\)為新圖上\(dis_{i,j}-h{i}+h_{j}\)

Code

lougu P5905
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,h[3010],cnt;
struct node{
    int to,d;
    bool operator < (const node &rhs) const{
        return d>rhs.d;
    }
};
priority_queue<node>q;
struct edge{
    int u,v,d,nxt,rd;
}e[9010];   //鏈式前向星
int hd[3010];
void add(int u,int v,int d){
    e[++cnt].d=d;e[cnt].v=v;
    e[cnt].nxt=hd[u];e[cnt].u=u;
    hd[u]=cnt;
}
bool bellman_ford(){      //計算h[u]
    for(int i=1;i<=n;i++) add(0,i,0);
    for(int i=1;i<=n;i++) h[i]=1e9;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=cnt;j++){
            int u=e[j].u,v=e[j].v,d=e[j].d;
            h[v]=min(h[v],h[u]+d);
        }
    }
    for(int j=1;j<=cnt;j++){
        int u=e[j].u,v=e[j].v,d=e[j].d;
        if(h[v]>h[u]+d) return 1;
    }
    for(int i=1;i<=m;i++) e[i].rd=e[i].d+h[e[i].u]-h[e[i].v];
    return 0;
}
int vis[3010],dis[3010],f[3010][3010];
void dijstra(int s){
    for(int i=1;i<=n;i++) vis[i]=0,dis[i]=1e9;
    q.push({s,0});
    dis[s]=0;
    while(!q.empty()){
        int u=q.top().to,d=q.top().d;
        q.pop();
        if(vis[u]) continue;
        vis[u]=1;
        for(int i=hd[u];i!=0;i=e[i].nxt){
            int v=e[i].v,ds=e[i].rd;
            if(dis[v]>d+ds){
                dis[v]=d+ds;
                q.push({v,d+ds});
            }
        }
    }
    for(int i=1;i<=n;i++) if(dis[i]!=1e9)f[s][i]=dis[i]-h[s]+h[i];else f[s][i]=1e9;
}
signed main(){
    cin>>n>>m;
    for(int i=1,x,y,o;i<=m;i++){
        cin>>x>>y>>o;
        add(x,y,o);
    }
    if(bellman_ford()){
        cout<<"-1";
        return 0;
    }
    for(int i=1;i<=n;i++) dijstra(i);
    int sum;
    for(int i=1;i<=n;i++){
        sum=0;
        for(int j=1;j<=n;j++){
            sum+=j*f[i][j];
        }
        cout<<sum<<endl;
    }
    return 0;
}

相關文章