zoukankan      html  css  js  c++  java
  • dij费用流模板

    参考博客:

    https://www.luogu.com.cn/blog/Mogician/Network-Flow-Guide


    可以先了解了解johnson全源最短路算法。

    核心思想为给每个点一个顶标,改边权为(h[x]+w-h[y])

    如果顶标设的好(设为最短路),就可以保证边权非负,然后跑dij。

    这个可以套在最小费用最大流上面,问题在于不可能每次流之后都重新跑spfa求最短路。

    而解决方法是给所有点的h加上这一次的最短路的dis,通过推理可以证明这是对的,详见参考博客。

    如果是最大费用,把一开始的边权取负即可(不考虑要消圈的话)。

    板子:
    https://www.luogu.com.cn/problem/P3381

    Code:

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    const int N = 1e6 + 5;
    
    int n, m, S, T;
    int x, y, z1, z2;
    
    int fi[N], to[N], nt[N], r[N], w[N], tot = 1;
    
    void link(int x, int y, int z1, int z2) {
    	nt[++ tot] = fi[x], to[tot] = y, r[tot] = z1, w[tot] = z2, fi[x] = tot;
    	nt[++ tot] = fi[y], to[tot] = x, r[tot] = 0, w[tot] = -z2, fi[y] = tot;
    }
    
    const int inf = 1e9;
    
    int d[N], d0, dis[N], bz[N];
    
    void spfa() {
    	fo(i, 1, n)	dis[i] = inf;
    	dis[S] = 0; d[d0 = 1] = S; bz[S] = 1;
    	for(int i = 1; i <= d0; i ++) {
    		int x = d[i]; bz[x] = 0;
    		for(int j = fi[x]; j; j = nt[j]) if(r[j]) {
    			int y = to[j];
    			if(dis[x] + w[j] < dis[y]) {
    				dis[y] = dis[x] + w[j];
    				if(!bz[y]) bz[y] = 1, d[++ d0] = y;
    			}
    		}
    	}
    }
    
    int h[N];
    
    struct P {
    	int x, y;
    	P(int _x = 0, int _y = 0) {
    		x = _x, y = _y;
    	}
    };
    
    bool operator < (P a, P b) { return a.y > b.y;}
    
    int fr[N];
    
    priority_queue<P> q;
    
    int us[N];
    
    ll ans1 = 0, ans = 0;
    
    int dij() {
    	while(!q.empty()) q.pop();
    	fo(i, 1, n)	dis[i] = inf, fr[i] = 0, us[i] = 0;
    	dis[S] = 0;
    	q.push(P(S, dis[S]));
    	while(q.size()) {
    		P b;
    		while(q.size()) {
    			b = q.top(); q.pop();
    			if(!us[b.x]) break;
    		}
    		if(us[b.x]) continue;
    		us[b.x] = 1;
    		for(int j = fi[b.x]; j; j = nt[j]) if(r[j]) {
    			int y = to[j];
    			int z = b.y + h[b.x] + w[j] - h[y];
    			if(z < dis[y]) {
    				fr[y] = j;
    				dis[y] = z;
    				q.push(P(y, dis[y]));
    			}
    		}
    	}
    	if(dis[T] == inf) return 0;
    	int mi = inf;
    	for(int p = T; p != S; p = to[fr[p] ^ 1]) mi = min(mi, r[fr[p]]);
    	ans1 += mi;
    	for(int p = T; p != S; p = to[fr[p] ^ 1]) {
    		ans += w[fr[p]]	 * mi;
    		r[fr[p]] -= mi, r[fr[p] ^ 1] += mi;
    	}
    	fo(i, 1, n) if(dis[i] < inf)
    		h[i] += dis[i];
    	return 1;
    }
    
    int main() {
    	scanf("%d %d %d %d", &n, &m, &S, &T);
    	fo(i, 1, m) {
    		scanf("%d %d %d %d", &x, &y, &z1, &z2);
    		link(x, y, z1, z2);
    	}
    	spfa();
    	fo(i, 1, n) h[i] = dis[i];
    	while(dij());
    	pp("%lld %lld
    ", ans1, ans);
    }
    
  • 相关阅读:
    css3-响应式布局
    css3-盒模型新增属性
    css3-弹性盒模型
    阿里天池超级码力复赛
    [状态压缩dp]Leetcode5.02双周赛 每个人戴不同帽子的方案数
    算法编程题:魔塔
    [Dijkstra贪心思想妙用]真实笔试题:传送门
    2020 力扣杯!Code Your Future 春季全国编程大赛 个人赛
    经典笔试算法题之打小怪兽
    两道经典面试算法题2020-3-20(打牌,最长上升字符串拼接)
  • 原文地址:https://www.cnblogs.com/coldchair/p/13460419.html
Copyright © 2011-2022 走看看