首页 > 其他分享 >Johnson全源最短路

Johnson全源最短路

时间:2022-11-14 18:14:52浏览次数:58  
标签:cnt Johnson int gpe 全源 sizeof 短路 dis

Johnson通过另一种方法给每条边重新标注边权。新建一个虚拟结点0,向其他所有点连一条边权为0的边,用Bellman-Ford或SPFA算法求出0到其他所有点的最短路记为gpe[i],对于一条x->y的边权为w的边,将边权重置为w+h[x]-h[y],以每个点为起点,跑n边dijkstra即可,时间复杂度O(nmlog2(m))。

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N=5e3+3;
const ll INF=1e9;
int h[N],tot,n,m,cnt[N];
ll gpe[N],dis[N];
bool in[N];
struct edge{
    int to,next,w;
}e[N<<1];
inline void add(int x,int y,int w){
    e[++tot]={y,h[x],w},h[x]=tot;
}
inline bool spfa(int s){
    queue<int>q;
    memset(gpe,0x3f,sizeof(gpe));
    memset(in,0,sizeof(in));
    gpe[s]=0;
    q.push(s);
    while(!q.empty()){
        int x=q.front();
        q.pop();
        in[x]=0;
        for(int i=h[x];i;i=e[i].next){
            int y=e[i].to;
            if(gpe[y]>gpe[x]+e[i].w){/*处理重力势能的最短路*/
                gpe[y]=gpe[x]+e[i].w;
                cnt[y]=cnt[x]+1;
                if(cnt[y]>n)return false;/*判断负环*/
                if(!in[y]){
                    in[y]=1;
                    q.push(y);
                }
            }
        }
    }
    return true;
}
inline void dijkstra(int s){
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;
    memset(in,0,sizeof(in));
    for(int i=1;i<=n;i++)dis[i]=INF;/*初始化*/
    dis[s]=0;
    q.push({0,s});
    while(!q.empty()){
        int x=q.top().second;
        q.pop();
        if(in[x])continue;
        in[x]=1;
        for(int i=h[x];i;i=e[i].next){
            int y=e[i].to;
            if(dis[y]>dis[x]+e[i].w){
                dis[y]=dis[x]+e[i].w;
                q.push({dis[y],y});
            }
        }
    }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }
    for(int i=1;i<=n;i++)add(0,i,0);/*虚拟结点连边*/
    if(!spfa(0))return cout<<-1,0;
    for(int x=1;x<=n;x++)for(int i=h[x];i;i=e[i].next)e[i].w+=gpe[x]-gpe[e[i].to];/*重新修改边权*/
    for(int i=1;i<=n;i++){
        dijkstra(i);
        ll ans=0;
        for(int j=1;j<=n;j++){
            if(dis[j]==INF)ans+=j*INF;
            else ans+=j*(dis[j]+gpe[j]-gpe[i]);/*计算出新的边权*/
        }
        cout<<ans<<'\n';
    }
    return 0;
}

标签:cnt,Johnson,int,gpe,全源,sizeof,短路,dis
From: https://www.cnblogs.com/safeng/p/16889857.html

相关文章

  • AtCoder Beginner Contest 277 E // 最短路
    CrystalSwitches题目来源:AtCoderBeginnerContest277E-CrystalSwitches题目链接:E-CrystalSwitches(atcoder.jp)题意给定一个\(N\)个点\(M\)条边的无向图。......
  • (AtCoder Beginner Contest 277)E(分层图+最短路 or bfs搜两种状态)
    E-CrystalSwitches题目大意:给你n个点,m条边,连接成一个无向图,每个边最初有一个状态(0or1)表示是否能够通过,同时给k个开关位于k的顶点上,每次点击开关会使得所有路的状......
  • #10077. 「一本通 3.2 练习 3」最短路计数
    问1~n的最短路有几个 #include<iostream>#include<cstring>#include<queue>usingnamespacestd;constintN=1e6+2,M=2e6+2;constintinf=0x3f3f3f3f,m......
  • 两个人从不同点出发,然后相遇的最短路问题
    MovingBothHands//可以选择一个中转点//也就是先正着走到这个点//然后再从这个点开始反着走//但是如果已经开始反着走了,那就只可以反着走图//正着和反着跑,有点奇......
  • 最短路径及最低成本算法实现模型
     在vs环境下进行的操作用两种方法分别模拟实现公园导航1.Dijkstra算法按路径长度递增次序来产生最短路径算法;  dist【】距离,path【】前结点  ①初始化......
  • 最短路板子
    floyedO(n^3) f[i][j]=min(f[i][j],f[i][k]+f[k][j]) memset(f,inf,sizeof(f));for(i=1;i<=m;i++)cin>>x>>y>>z,f[x][y]=f[y][x]=z;for......
  • 最短路中对步数有要求的问题
    一般就是走的步数在k步内,或者恰好是k步有边数限制的最短路如果k比较小大体有两种实现方法:Bellman_Ford直接每一次都把能走的边都走一次,一共重复k次#include<bits/st......
  • 864. 获取所有钥匙的最短路径
    864.获取所有钥匙的最短路径题解:bfs总共不超过6把钥匙,通过位运算保存钥匙classSolution{publicintshortestPathAllKeys(String[]grid){in......
  • Leetcode第864题:获取所有钥匙的最短路径(Shortest path to get all keys)
    解题思路想到最短路径问题,自然想到用BFS解决问题,但是只记录位置还不够,还需要记录当前拥有的钥匙状态。需要的数据结构钥匙的个数是\(1-6\),用一个二进制数表示钥匙的状......
  • 同余最短路
    跳楼机题目背景DJL为了避免成为一只咸鱼,来找srwudi学习压代码的技巧。题目描述Srwudi的家是一幢\(h\)层的摩天大楼。由于前来学习的蒟蒻越来越多,srwudi改造了一......