zoukankan      html  css  js  c++  java
  • Johnson 全源最短路

    题目链接

    本来有负边的最短路应该是O(n^3)

    这个算法把负权图改成了正权图,可以跑dij,能够用来优化多次涉及spfa的算法,比如费用流

    十分神奇

    核心想法:

    1.建立0--->(1--n),然后跑个spfa,得到d[i--n],

    2.把x--->y----len改成    x--->y-----len - d[y] + d[x]

    最后的结果就是a----b = dis[b] - d[b] + d[a];

    完了

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    using namespace std;
    typedef long long ll;
    ll INF = 1e17;
    
    const int maxn = 2e5 + 111;
    struct Node {
    	int p;
    	ll len;
    	Node(int a, ll b) :p(a), len(b) {}
    };
    vector<Node>G[maxn];
    void add(int be, int en,int len) {
    	G[be].push_back(Node(en, len));
    }
    
    int n, m;
    ll dis[maxn];
    int cnt[maxn];
    int h[maxn];
    int vis[maxn];
    
    
    int spfa(int s) {
    	queue<int>que;
    	for (int i = 0; i <= n ; i++) {
    		vis[i] = cnt[i] = 0;
    		dis[i] = INF;
    	}
    	que.push(s);
    	dis[s] = 0;
    	while (que.size()) {
    		int x = que.front();
    		que.pop();
    		vis[x] = 0;
    		for (int i = 0; i < G[x].size(); i++) {
    			int p = G[x][i].p;
    			ll ln = G[x][i].len;
    			if (dis[p] > dis[x] + ln) {
    				dis[p] = dis[x] + ln;
    				if (vis[p] == 0) {
    					vis[p] = 1;
    					que.push(p);
    					if (++cnt[p] > n) return 1;
    				}
    			}
    		}
    	}
    	return 0;
    }
    bool operator <(const Node a, const Node b) {
    	return a.len > b.len;
    }
    
    int dij(int s) {
    	for (int i = 0; i <= n; i++) {
    		vis[i] = 0;
    		dis[i] = INF;
    	}
    	priority_queue<Node>que;
    	que.push(Node(s, 0));
    	dis[s] = 0;
    
    	while (que.size()) {
    		Node ans = que.top();
    		que.pop();
    		if (vis[ans.p]) continue;
    		vis[ans.p] = 1;
    
    		for (int i = 0; i < G[ans.p].size(); i++) {
    			int p = G[ans.p][i].p;
    			ll ln = G[ans.p][i].len;
    			if (dis[p] > dis[ans.p] + ln) {
    				dis[p] = dis[ans.p] + ln;
    				que.push(Node(p, dis[p]));
    			}
    		}
    	}
    	return 0;
    }
    vector<ll> ins;
    
    
    int main() {
    	scanf("%d %d", &n, &m);
    	for (int i = 1; i <= n; i++) {
    		add(0, i, 0);
    	}
    
    	for (int i = 0; i < m; i++) {
    		int be, en, len;
    		scanf("%d %d %d", &be, &en, &len);
    
    		add(be, en, len);
    	}
    
    	int f = spfa(0);
    	if (f) {
    		printf("-1
    ");
    		return 0;
    	}
    	for (int i = 0; i <= n; i++) h[i] = dis[i];
    
    	for (int i = 1; i <= n; i++) {
    		for (int j = 0; j < G[i].size(); j++) {
    			G[i][j].len += dis[i] - dis[G[i][j].p];
    		}
    	}
    
    	for (int i = 1; i <= n; i++) {
    		dij(i);
    		ll ans = 0;
    		for (int j = 1; j <= n; j++) {
    			if (dis[j] == INF) dis[j] = 1e9;
    			else dis[j] -= h[i] - h[j];
    
    			ans += 1LL*j*dis[j];
    		}
    		ins.push_back(ans);
    	}
    	for (int i = 0; i < ins.size(); i++) {
    		printf("%lld
    ", ins[i]);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    matlab cell
    matlab linux 快捷键设置——有问题还是要解决
    latex 小结
    TOJ 1258 Very Simple Counting
    TOJ 2888 Pearls
    HDU 1248 寒冰王座
    TOJ 3486 Divisibility
    TOJ 3635 过山车
    TOJ 1840 Jack Straws
    HDU 4460 Friend Chains
  • 原文地址:https://www.cnblogs.com/lesning/p/14086253.html
Copyright © 2011-2022 走看看