Johnson最短路板子

我们知道johnson最常见的做法是 spfa+dijkstra

我们先有spfa板子:

bool spfa(int st){
    queue<int>q;
    memset(h,63,sizeof h);
    h[st]=0;
    vis[st]=1;
    q.push(st);
    while(!q.empty()){
        int u=q.front();q.pop();
        vis[u]=0;
        for(int e=head[u];e;e=edge[e].next){//默认使用邻接表存边
            int v=edge[e].to;
            if(h[v]>h[u]+edge[e].dis){
                h[v]=h[u]+edge[e].dis;
                if(!vis[v]){
                    vis[v]=1;
                    q.push(v);
                    if(++t[v]==n+1)return false;//负环
                }
            }
        }
    }
    return true;
}

而后是STL 优先队列(在这里我弄成了小根堆)优化dijkstra

struct node{
    ll dis;int id;
    bool operator <(const node&a)const{
        return dis>a.dis;
    }
    node(ll d,int x){
        dis=d,id=x;
    }
};
void dijkstra(int st){
    memset(vis,0,sizeof vis);
    for(int i=1;i<=n;i++)dis[i]=INF;
    dis[st]=0;
    priority_queue<node>q;
    q.push(node(0,st));
    while(!q.empty()){
        int u=q.top().id;q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(int e=head[u];e;e=edge[e].next){
            int v=edge[e].to;
            if(dis[v]>dis[u]+edge[e].dis){
                dis[v]=dis[u]+edge[e].dis;
                if(!vis[v])q.push(node(dis[v],v));
            }
        }
    }
}

Johnson题目参考 洛谷P5905

//johnson最短路算法 
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5005;
const ll INF = 1e9;

struct Edge{
    int next,to;
    ll dis;
}edge[2*N];
struct node{
    ll dis;int id;
    bool operator <(const node&a)const{
        return dis>a.dis;
    }
    node(ll d,int x){
        dis=d,id=x;
    }
};
int n,m,tot;
int head[N],t[N];
ll dis[N],h[N];
bool vis[N];

void add_edge(int from,int to,int dis){
    edge[++tot].next=head[from];
    edge[tot].to=to;
    edge[tot].dis=dis;
    head[from]=tot;
}

bool spfa(int st){
    queue<int>q;
    memset(h,63,sizeof h);
    h[st]=0;
    vis[st]=1;
    q.push(st);
    while(!q.empty()){
        int u=q.front();q.pop();
        vis[u]=0;
        for(int e=head[u];e;e=edge[e].next){
            int v=edge[e].to;
            if(h[v]>h[u]+edge[e].dis){
                h[v]=h[u]+edge[e].dis;
                if(!vis[v]){
                    vis[v]=1;
                    q.push(v);
                    if(++t[v]==n+1)return false;
                }
            }
        }
    }
    return true;
}

void dijkstra(int st){
    memset(vis,0,sizeof vis);
    for(int i=1;i<=n;i++)dis[i]=INF;
    dis[st]=0;
    priority_queue<node>q;
    q.push(node(0,st));
    while(!q.empty()){
        int u=q.top().id;q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(int e=head[u];e;e=edge[e].next){
            int v=edge[e].to;
            if(dis[v]>dis[u]+edge[e].dis){
                dis[v]=dis[u]+edge[e].dis;
                if(!vis[v])q.push(node(dis[v],v));
            }
        }
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v;ll w;
        scanf("%d%d%lld",&u,&v,&w);
        add_edge(u,v,w);
    }
    for(int i=1;i<=n;i++)add_edge(0,i,0);
    if(!spfa(0)){
        printf("-1");
        return 0;
    }
    for(int u=1;u<=n;u++){
        for(int e=head[u];e;e=edge[e].next){
            edge[e].dis+=h[u]-h[edge[e].to];
        }
    }
    for(int u=1;u<=n;u++){
        dijkstra(u);
        ll ans=0;
        for(ll v=1;v<=n;v++){
               if(dis[v]==INF)ans+=v*INF;
               else ans+=v*(dis[v]+h[v]-h[u]);
          }
         printf("%lld\n",ans);
    }
    return 0;
    
}

 

posted @ 2020-12-19 23:02  _Famiglistimo  阅读(90)  评论(0编辑  收藏  举报