Luo Gu · [24 network flow problem] transportation problem

~ Ann is here shown signs of portal: Luo Gu P4015 transportation problem

answer

Because the amount of the initial amount of goods and changes are identified, so this is the maximum / minimum cost flow .

In fact, the direct meaning built by topic map on it. It represents even distribution of goods, b connected from each T represents the need to limit the number of goods from the store S b to each of a warehouse. It can even cost side stream in accordance with the meaning of the questions between a and b.

For the text of the two questions of course we can write two spfa, run a maximum cost flow, ran a minimum cost flow. But in fact, for maximum cost flow, we can all take the right side opposite number then run minimum cost flow, and then the results were opposite number. In this case it can be a lot easier. [ May be my own problems, I ask the right side of the minimum cost flow when taken opposite number and then throw the maximum flow ran to get out QAQ ]

The code -

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define maxn 500
#define maxm 200005
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
int read() {
	int x = 0, f = 1, ch = getchar();
	while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
	while(isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
	return x * f;
}

struct edge {int to, w, f, nxt;} e[maxm], e2[maxm];
int head[maxn], k = 0;
void add(int u, int v, int w, int f) {
	e[k] = {v, w, f, head[u]}; head[u] = k++;
	e[k] = {u, 0, -f, head[v]}; head[v] = k++;
} 

int S, T;
int dis[maxn], pre[maxn], incf[maxn];
bool vis[maxn];
bool spfa() {
	memset(dis, 0x3f, sizeof dis); dis[S] = 0;
	memset(vis, 0, sizeof vis); vis[S] = true;
	memset(incf, 0x3f, sizeof incf); incf[S] = INF; 
	queue<int> q; q.push(S);
	while(q.size()) {
		register int u = q.front(), v; q.pop(); vis[u] = false;
		for(int i = head[u]; ~i; i = e[i].nxt) {
			v = e[i].to; if(e[i].w && dis[u] + e[i].f < dis[v]) {
				dis[v] = dis[u] + e[i].f;
				incf[v] = min(incf[u], e[i].w); pre[v] = i;
				if(!vis[v]) q.push(v), vis[v] = true;
			}
		}
	}
	if(dis[T] == INF) return false; return true;
}

ll ans = 0;
void update() {
	register int u = T, i;
	while(u != S) {
		i = pre[u];
		e[i].w -= incf[T], e[i ^ 1].w += incf[T];
		u = e[i ^ 1].to;
	}
	ans += 1ll * incf[T] * dis[T];
}

int n, m, a[maxn], b[maxn]; 
signed main() {
	memset(head, -1, sizeof head);
	n = read(), m = read();
	S = 0, T = n + m + 1;//↓按照提议建图
	for(int i = 1, x; i <= n; i++) a[i] = read(), add(S, i, a[i], 0);
	for(int i = 1, x; i <= m; i++) b[i] = read(), add(i + n, T, b[i], 0);
	for(int i = 1; i <= n; i++) for(int j = 1, x; j <= m; j++)
		x = read(), add(i, j + n, INF, x);
	
	for(int i = 0; i < k; i++) e2[i] = e[i];//e2存放一下原图
	while(spfa()) update();
	printf("%lld\n", ans); ans = 0;
	
	for(int i = 0; i < k; i++) e[i] = e2[i], e[i].f = -e[i].f;//把原图换回来
	while(spfa()) update();
	printf("%lld\n", -ans);
	return 0;
}

Meet the assessment
:) --End--

Published 158 original articles · won praise 23 · views 20000 +

Guess you like

Origin blog.csdn.net/qq_43326267/article/details/104189448