• 网络流模板大全


    说“大全”,其实也不见得全。。。

    1、最大流,Dinic 模板。[LOJ#101]

    这题 Dinic 需要卡常才能过,主要是 BFS 从汇点开始搜更快。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    #define rep(i, s, t) for(int i = (s); i <= (t); i++)
    #define dwn(i, s, t) for(int i = (s); i >= (t); i--)
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 1000010
    #define maxm 8000010
    #define oo 2147483647
    #define LL long long
    
    struct Edge {
    	int from, to, flow;
    	Edge() {}
    	Edge(int _1, int _2, int _3): from(_1), to(_2), flow(_3) {}
    };
    struct Dinic {
    	int n, m, s, t, head[maxn], nxt[maxm];
    	Edge es[maxm];
    	int vis[maxn], Q[maxn], hd, tl;
    	int cur[maxn];
    	
    	void init() {
    		m = 0; memset(head, -1, sizeof(head));
    		return ;
    	}
    	void setn(int _) {
    		n = _;
    		return ;
    	}
    	
    	void AddEdge(int a, int b, int c) {
    		es[m] = Edge(a, b, c); nxt[m] = head[a]; head[a] = m++;
    		es[m] = Edge(b, a, 0); nxt[m] = head[b]; head[b] = m++;
    		return ;
    	}
    	
    	bool BFS() {
    		memset(vis, 0, sizeof(vis));
    		vis[t] = 1;
    		hd = tl = 0; Q[++tl] = t;
    		while(hd < tl) {
    			int u = Q[++hd];
    			for(int i = head[u]; i != -1; i = nxt[i]) {
    				Edge& e = es[i^1];
    				if(!vis[e.from] && e.flow) {
    					vis[e.from] = vis[u] + 1;
    					Q[++tl] = e.from;
    				}
    			}
    		}
    		return vis[s] > 0;
    	}
    	
    	LL DFS(int u, int a) {
    		if(u == t || !a) return a;
    		LL flow = 0, f;
    		for(int& i = cur[u]; i != -1; i = nxt[i]) {
    			Edge& e = es[i];
    			if(vis[e.to] == vis[u] - 1 && (f = DFS(e.to, min(a, e.flow)))) {
    				flow += f; a -= f;
    				e.flow -= f; es[i^1].flow += f;
    				if(!a) return flow;
    			}
    		}
    		return flow;
    	}
    	
    	LL MaxFlow(int _s, int _t) {
    		s = _s; t = _t;
    		LL flow = 0;
    		while(BFS()) {
    			rep(i, 1, n) cur[i] = head[i];
    			flow += DFS(s, oo);
    		}
    		return flow;
    	}
    } sol;
    
    int main() {
    	int n = read(), m = read(), s = read(), t = read();
    	sol.init();
    	rep(i, 1, m) {
    		int u = read(), v = read(), c = read();
    		sol.AddEdge(u, v, c);
    	}
    	sol.setn(n);
    	printf("%lld
    ", sol.MaxFlow(s, t));
    	
    	return 0;
    }
    

    2、最小费用最大流,ZKW 模板。[LOJ#102]

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define rep(i, s, t) for(int i = (s); i <= (t); i++)
    #define dwn(i, s, t) for(int i = (s); i >= (t); i--)
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 410
    #define maxm 30010
    #define oo 2147483647
    
    struct Edge {
    	int from, to, flow, cost;
    	Edge() {}
    	Edge(int _1, int _2, int _3, int _4): from(_1), to(_2), flow(_3), cost(_4) {}
    };
    struct ZKW {
    	int s, t, cost, ans, n, m, head[maxn], nxt[maxm];
    	Edge es[maxm];
    	int d[maxn];
    	deque <int> Q;
    	bool inq[maxn];
    	bool vis[maxn];
    	
    	void init() {
    		m = 0; memset(head, -1, sizeof(head));
    		return ;
    	}
    	void setn(int _) {
    		n = _;
    		return ;
    	}
    	
    	void AddEdge(int a, int b, int c, int d) {
    		es[m] = Edge(a, b, c, d); nxt[m] = head[a]; head[a] = m++;
    		es[m] = Edge(b, a, 0, -d); nxt[m] = head[b]; head[b] = m++;
    		return ;
    	}
    	
    	bool BFS() {
    		rep(i, 1, n) d[i] = oo;
    		Q.push_back(t); inq[t] = 1;
    		d[t] = 0;
    		while(!Q.empty()) {
    			int u = Q.front(); Q.pop_front(); inq[u] = 0;
    			for(int i = head[u]; i != -1; i = nxt[i]) {
    				Edge& e = es[i^1];
    				if(d[e.from] > d[u] + e.cost && e.flow) {
    					d[e.from] = d[u] + e.cost;
    					if(!inq[e.from]) {
    						inq[e.from] = 1;
    						if(Q.empty() || d[Q.front()] >= d[e.from]) Q.push_front(e.from);
    						else Q.push_back(e.from);
    					}
    				}
    			}
    		}
    		if(d[s] == oo) return 0;
    		cost = d[s];
    		return 1;
    	}
    	
    	int DFS(int u, int a) {
    		if(u == t || !a){ ans += cost * a; return a; }
    		if(vis[u]) return 0;
    		vis[u] = 1;
    		int flow = 0, f;
    		for(int i = head[u]; i != -1; i = nxt[i]) {
    			Edge& e = es[i];
    			if(d[e.to] == d[u] - e.cost && e.flow && (f = DFS(e.to, min(e.flow, a)))) {
    				flow += f; a -= f;
    				e.flow -= f; es[i^1].flow += f;
    				if(!a) return flow;
    			}
    		}
    		return flow;
    	}
    	
    	int MaxFlow(int _s, int _t) {
    		s = _s; t = _t;
    		int flow = 0, f;
    		while(BFS())
    			do {
    				memset(vis, 0, sizeof(vis));
    				f = DFS(s, oo);
    				flow += f;
    			} while(f);
    		return flow;
    	}
    } sol;
    
    int main() {
    	int n = read(), m = read();
    	sol.init();
    	rep(i, 1, m) {
    		int a = read(), b = read(), c = read(), d = read();
    		sol.AddEdge(a, b, c, d);
    	}
    	sol.setn(n);
    	printf("%d ", sol.MaxFlow(1, n));
    	printf("%d
    ", sol.ans);
    	
    	return 0;
    }
    

    3、无源汇有上下界可行流。[LOJ#115]

    先强行让每条边流成下界,那么现在可能有一些点出入不平衡, 需要调整。假设节点 (u) 出大于入,那么从 (u) 向新建汇点连一条出流 - 入流的边;假设节点 (v) 入大于出,那么从新建源点向 (v) 连一条入流 - 出流的边。(因为我们需要通过原图将流量调至平衡,所以出多反而需要连出边,入多需要连入边)

    如果新图最大流不能把源点出发(或到达汇点)的流量流满,就说明无解。若有解,则最终每条边的流量 = 流量下界 + 新图中对应边的流量。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    #define rep(i, s, t) for(int i = (s); i <= (t); i++)
    #define dwn(i, s, t) for(int i = (s); i >= (t); i--)
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 210
    #define maxm 61210
    #define oo 2147483647
    
    struct Edge {
    	int from, to, flow;
    	Edge() {}
    	Edge(int _1, int _2, int _3): from(_1), to(_2), flow(_3) {}
    };
    struct Dinic {
    	int n, m, s, t, head[maxn], nxt[maxm];
    	Edge es[maxm];
    	int vis[maxn], Q[maxn], hd, tl;
    	int cur[maxn];
    	
    	void init() {
    		m = 0; memset(head, -1, sizeof(head));
    		return ;
    	}
    	void setn(int _) {
    		n = _;
    		return ;
    	}
    	
    	void AddEdge(int a, int b, int c) {
    		es[m] = Edge(a, b, c); nxt[m] = head[a]; head[a] = m++;
    		es[m] = Edge(b, a, 0); nxt[m] = head[b]; head[b] = m++;
    		return ;
    	}
    	
    	bool BFS() {
    		memset(vis, 0, sizeof(vis));
    		vis[t] = 1;
    		hd = tl = 0; Q[++tl] = t;
    		while(hd < tl) {
    			int u = Q[++hd];
    			for(int i = head[u]; i != -1; i = nxt[i]) {
    				Edge& e = es[i^1];
    				if(!vis[e.from] && e.flow) {
    					vis[e.from] = vis[u] + 1;
    					Q[++tl] = e.from;
    				}
    			}
    		}
    		return vis[s] > 0;
    	}
    	
    	int DFS(int u, int a) {
    		if(u == t || !a) return a;
    		int flow = 0, f;
    		for(int& i = cur[u]; i != -1; i = nxt[i]) {
    			Edge& e = es[i];
    			if(vis[e.to] == vis[u] - 1 && (f = DFS(e.to, min(a, e.flow)))) {
    				flow += f; a -= f;
    				e.flow -= f; es[i^1].flow += f;
    				if(!a) return flow;
    			}
    		}
    		return flow;
    	}
    	
    	int MaxFlow(int _s, int _t) {
    		s = _s; t = _t;
    		int flow = 0;
    		while(BFS()) {
    			rep(i, 1, n) cur[i] = head[i];
    			flow += DFS(s, oo);
    		}
    		return flow;
    	}
    } sol;
    
    int eid[maxm], low[maxm], in_f[maxn], out_f[maxn];
    
    int main() {
    	int n = read(), m = read(), s = n + 1, t = n + 2, sum = 0;
    	sol.init();
    	sol.setn(t);
    	rep(i, 1, m) {
    		int u = read(), v = read(), l = read(), r = read();
    		if(l > r) return puts("NO"), 0;
    		eid[i] = sol.m; low[i] = l;
    		sol.AddEdge(u, v, r - l);
    		in_f[v] += l; out_f[u] += l;
    	}
    	rep(i, 1, n)
    		if(in_f[i] > out_f[i]) sol.AddEdge(s, i, in_f[i] - out_f[i]), sum += in_f[i] - out_f[i];
    		else if(out_f[i] > in_f[i]) sol.AddEdge(i, t, out_f[i] - in_f[i]);
    	
    	if(sol.MaxFlow(s, t) < sum) return puts("NO"), 0;
    	puts("YES");
    	rep(i, 1, m) printf("%d
    ", low[i] + sol.es[eid[i]^1].flow);
    	
    	return 0;
    }
    

    4、有源汇有上下界最大流。[LOJ#116]

    从原图汇点向原图源点加一条容量无穷下界为 (0) 的边 (e),求出可行流,(若存在可行流)然后从原图中的源点到原图汇点跑一遍最大流就是答案。

    有两点小问题:

    1. 新建的源点、汇点是否会影响最后那一遍最大流?

    A:不会的,因为如果存在解,那么新建的边就是满流的,即它们都指向源,或从汇指出,不肯能通过他们形成增广路。

    1. 为什么直接跑最大流就是答案,不需要加上求完可行流后 (e) 上的流量吗?

    A:不需要,因为第二遍最大流会把第一次在 (e) 上跑出的流量自动退回去——它会自动给你把这部分答案算上。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    #define rep(i, s, t) for(int i = (s); i <= (t); i++)
    #define dwn(i, s, t) for(int i = (s); i >= (t); i--)
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 212
    #define maxm 20412
    #define oo 2147483647
    
    struct Edge {
    	int from, to, flow;
    	Edge() {}
    	Edge(int _1, int _2, int _3): from(_1), to(_2), flow(_3) {}
    };
    struct Dinic {
    	int n, m, s, t, head[maxn], nxt[maxm];
    	Edge es[maxm];
    	int vis[maxn], Q[maxn], hd, tl;
    	int cur[maxn];
    	
    	void init() {
    		m = 0; memset(head, -1, sizeof(head));
    		return ;
    	}
    	void setn(int _) {
    		n = _;
    		return ;
    	}
    	
    	void AddEdge(int a, int b, int c) {
    		es[m] = Edge(a, b, c); nxt[m] = head[a]; head[a] = m++;
    		es[m] = Edge(b, a, 0); nxt[m] = head[b]; head[b] = m++;
    		return ;
    	}
    	
    	bool BFS() {
    		memset(vis, 0, sizeof(vis));
    		vis[t] = 1;
    		hd = tl = 0; Q[++tl] = t;
    		while(hd < tl) {
    			int u = Q[++hd];
    			for(int i = head[u]; i != -1; i = nxt[i]) {
    				Edge& e = es[i^1];
    				if(!vis[e.from] && e.flow) {
    					vis[e.from] = vis[u] + 1;
    					Q[++tl] = e.from;
    				}
    			}
    		}
    		return vis[s] > 0;
    	}
    	
    	int DFS(int u, int a) {
    		if(u == t || !a) return a;
    		int flow = 0, f;
    		for(int& i = cur[u]; i != -1; i = nxt[i]) {
    			Edge& e = es[i];
    			if(vis[e.to] == vis[u] - 1 && (f = DFS(e.to, min(a, e.flow)))) {
    				flow += f; a -= f;
    				e.flow -= f; es[i^1].flow += f;
    				if(!a) return flow;
    			}
    		}
    		return flow;
    	}
    	
    	int MaxFlow(int _s, int _t) {
    		s = _s; t = _t;
    		int flow = 0;
    		while(BFS()) {
    			rep(i, 1, n) cur[i] = head[i];
    			flow += DFS(s, oo);
    		}
    		return flow;
    	}
    } sol;
    
    int eid[maxm], low[maxm], in_f[maxn], out_f[maxn];
    
    int main() {
    	int n = read(), m = read(), S = read(), T = read(), s = n + 1, t = n + 2, sum = 0;
    	sol.init();
    	sol.setn(t);
    	rep(i, 1, m) {
    		int u = read(), v = read(), l = read(), r = read();
    		if(l > r) return puts("please go home to sleep"), 0;
    		eid[i] = sol.m; low[i] = l;
    		sol.AddEdge(u, v, r - l);
    		in_f[v] += l; out_f[u] += l;
    	}
    	sol.AddEdge(T, S, oo);
    	rep(i, 1, n)
    		if(in_f[i] > out_f[i]) sol.AddEdge(s, i, in_f[i] - out_f[i]), sum += in_f[i] - out_f[i];
    		else if(out_f[i] > in_f[i]) sol.AddEdge(i, t, out_f[i] - in_f[i]);
    	
    	if(sol.MaxFlow(s, t) < sum) return puts("please go home to sleep"), 0;
    	printf("%d
    ", sol.MaxFlow(S, T));
    	
    	return 0;
    }
    

    5、有源汇有上下界最小流。[LOJ#117]

    从原图汇点向汇点加一条容量无穷下界为 (0) 的边 (e),求出可行流,记此时边 (e) 上的流量为 (flow_e);然后删掉边 (e),从原图汇点向原图源点跑一遍最大流,这次最大流答案记为 (f),那么最终答案为 (flow_e - f)

    可能产生的疑惑见上一题。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    #define rep(i, s, t) for(int i = (s); i <= (t); i++)
    #define dwn(i, s, t) for(int i = (s); i >= (t); i--)
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 50013
    #define maxm 350022
    #define oo 2147483647
    
    struct Edge {
    	int from, to, flow;
    	Edge() {}
    	Edge(int _1, int _2, int _3): from(_1), to(_2), flow(_3) {}
    };
    struct Dinic {
    	int n, m, s, t, head[maxn], nxt[maxm];
    	Edge es[maxm];
    	int vis[maxn], Q[maxn], hd, tl;
    	int cur[maxn];
    	
    	void init() {
    		m = 0; memset(head, -1, sizeof(head));
    		return ;
    	}
    	void setn(int _) {
    		n = _;
    		return ;
    	}
    	
    	void AddEdge(int a, int b, int c) {
    		es[m] = Edge(a, b, c); nxt[m] = head[a]; head[a] = m++;
    		es[m] = Edge(b, a, 0); nxt[m] = head[b]; head[b] = m++;
    		return ;
    	}
    	
    	bool BFS(bool block) {
    		memset(vis, 0, sizeof(vis));
    		vis[t] = 1;
    		hd = tl = 0; Q[++tl] = t;
    		while(hd < tl) {
    			int u = Q[++hd];
    			for(int i = head[u]; i != -1; i = nxt[i]) {
    				Edge& e = es[i^1];
    				if(block && e.from == s && e.to == t) continue;
    				if(!vis[e.from] && e.flow) {
    					vis[e.from] = vis[u] + 1;
    					Q[++tl] = e.from;
    				}
    			}
    		}
    		return vis[s] > 0;
    	}
    	
    	int DFS(int u, int a, bool block) {
    		if(u == t || !a) return a;
    		int flow = 0, f;
    		for(int& i = cur[u]; i != -1; i = nxt[i]) {
    			Edge& e = es[i];
    			if(block && u == s && e.to == t) continue;
    			if(vis[e.to] == vis[u] - 1 && (f = DFS(e.to, min(a, e.flow), block))) {
    				flow += f; a -= f;
    				e.flow -= f; es[i^1].flow += f;
    				if(!a) return flow;
    			}
    		}
    		return flow;
    	}
    	
    	int MaxFlow(int _s, int _t, bool block) {
    		s = _s; t = _t;
    		int flow = 0;
    		while(BFS(block)) {
    			rep(i, 1, n) cur[i] = head[i];
    			flow += DFS(s, oo, block);
    		}
    		return flow;
    	}
    } sol;
    
    int eid[maxm], low[maxm], in_f[maxn], out_f[maxn];
    
    int main() {
    	int n = read(), m = read(), S = read(), T = read(), s = n + 1, t = n + 2, sum = 0;
    	sol.init();
    	sol.setn(t);
    	rep(i, 1, m) {
    		int u = read(), v = read(), l = read(), r = read();
    		if(l > r) return puts("please go home to sleep"), 0;
    		eid[i] = sol.m; low[i] = l;
    		sol.AddEdge(u, v, r - l);
    		in_f[v] += l; out_f[u] += l;
    	}
    	int cure = sol.m;
    	sol.AddEdge(T, S, oo);
    	rep(i, 1, n)
    		if(in_f[i] > out_f[i]) sol.AddEdge(s, i, in_f[i] - out_f[i]), sum += in_f[i] - out_f[i];
    		else if(out_f[i] > in_f[i]) sol.AddEdge(i, t, out_f[i] - in_f[i]);
    	
    	int flow = sol.MaxFlow(s, t, 0);
    	int tmp = sol.es[cure^1].flow;
    	if(flow < sum) return puts("please go home to sleep"), 0;
    	printf("%d
    ", tmp - sol.MaxFlow(T, S, 1));
    	
    	return 0;
    }
    

    6、最小费用可行流(带负环、下界)。[ZZOJ#30]

    先强行所有边权为负的边流满上界,边权为正的边流成下界,然后用可行流的方法调整。注意调整时跑的是最小费用最大流,而不是最小费用流。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define rep(i, s, t) for(int i = (s); i <= (t); i++)
    #define dwn(i, s, t) for(int i = (s); i >= (t); i--)
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 310
    #define maxm 6010
    #define oo 2147483647
    #define LL long long
    
    struct Edge {
    	int from, to, flow, cost;
    	Edge() {}
    	Edge(int _1, int _2, int _3, int _4): from(_1), to(_2), flow(_3), cost(_4) {}
    };
    struct ZKW {
    	int n, m, s, t, cost, head[maxn], nxt[maxm];
    	LL ans;
    	Edge es[maxm];
    	int d[maxn];
    	bool inq[maxn];
    	deque <int> Q;
    	bool vis[maxn];
    	
    	void init() {
    		m = 0; memset(head, -1, sizeof(head));
    		return ;
    	}
    	void setn(int _) {
    		n = _;
    		return ;
    	}
    	
    	void AddEdge(int a, int b, int c, int d) {
    		es[m] = Edge(a, b, c, d); nxt[m] = head[a]; head[a] = m++;
    		es[m] = Edge(b, a, 0, -d); nxt[m] = head[b]; head[b] = m++;
    		return ;
    	}
    	
    	bool BFS() {
    		rep(i, 1, n) d[i] = oo;
    		d[t] = 0;
    		Q.push_back(t); inq[t] = 1;
    		while(!Q.empty()) {
    			int u = Q.front(); Q.pop_front(); inq[u] = 0;
    			for(int i = head[u]; i != -1; i = nxt[i]) {
    				Edge& e = es[i^1];
    				if(d[e.from] > d[u] + e.cost && e.flow) {
    					d[e.from] = d[u] + e.cost;
    					if(!inq[e.from]) {
    						inq[e.from] = 1;
    						if(Q.empty() || d[e.from] <= d[Q.front()]) Q.push_front(e.from);
    						else Q.push_back(e.from);
    					}
    				}
    			}
    		}
    		if(d[s] == oo) return 0;
    		cost = d[s];
    		return 1;
    	}
    	
    	int DFS(int u, int a) {
    		if(u == t || !a) return ans += (LL)cost * a, a;
    		if(vis[u]) return 0;
    		vis[u] = 1;
    		int flow = 0, f;
    		for(int i = head[u]; i != -1; i = nxt[i]) {
    			Edge& e = es[i];
    			if(d[e.to] == d[u] - e.cost && (f = DFS(e.to, min(a, e.flow)))) {
    				flow += f; a -= f;
    				e.flow -= f; es[i^1].flow += f;
    				if(!a) return flow;
    			}
    		}
    		return flow;
    	}
    	
    	int MaxFlow(int _s, int _t) {
    		s = _s; t = _t;
    		int flow = 0, f;
    		while(BFS())
    			do {
    				memset(vis, 0, sizeof(vis));
    				f = DFS(s, oo);
    				flow += f;
    			} while(f);
    		return flow;
    	}
    } sol;
    
    int in_f[maxn], out_f[maxn], eid[maxm], low[maxm];
    bool rev[maxm];
    
    int main() {
    	int n = read(), m = read(), s = n + 1, t = s + 1;
    	LL ans = 0;
    	sol.init(); sol.setn(t);
    	rep(i, 1, m) {
    		int a = read(), b = read(), lower = read(), upper = read(), cost = read();
    		if(cost >= 0) {
    			ans += (LL)lower * cost;
    			in_f[b] += lower; out_f[a] += lower;
    			low[i] = lower; eid[i] = sol.m;
    			sol.AddEdge(a, b, upper - lower, cost);
    		}
    		if(cost < 0) {
    			ans += (LL)upper * cost;
    			in_f[b] += upper; out_f[a] += upper;
    			low[i] = upper; eid[i] = sol.m; rev[i] = 1;
    			sol.AddEdge(b, a, upper - lower, -cost);
    		}
    	}
    	int need_f = 0;
    	rep(i, 1, n) {
    		if(in_f[i] > out_f[i]) sol.AddEdge(s, i, in_f[i] - out_f[i], 0), need_f += in_f[i] - out_f[i];
    		if(out_f[i] > in_f[i]) sol.AddEdge(i, t, out_f[i] - in_f[i], 0);
    	}
    	if(sol.MaxFlow(s, t) < need_f) return puts("QAQ"), 0;
    	printf("%lld
    ", ans + sol.ans);
    //	rep(i, 1, m) printf("%d
    ", low[i] + (sol.es[eid[i]^1].flow * (rev[i] ? -1 : 1)));
    	
    	return 0;
    }
    
  • 相关阅读:
    实验5 函数
    实验4 在分支循环结构中调用自定义函数
    Play 内置标签
    POI 正常输出WORD 文档
    用户WORD模板写文件
    Spring 注解过滤
    Spring 循环依赖
    Spring 表单标签
    WebService 客户端生成服务端代码
    Jquery 常用函数
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/7900457.html
Copyright © 2020-2023  润新知