Luogu P4015 运输问题

题目链接 \(Click\) \(Here\)

继续颓网络流\(hhhhh\),虽然这次写的是个大水题,但是早上水一个网络流果然还是让人心情舒畅啊~

最大费用最大流不用非得反着费用建边.只要没有正环,初始化的时候小心一点就好啦~

#include <bits/stdc++.h>
using namespace std;

const int INF = 0x3f3f3f3f;

int cnt = -1, head[210];

struct edge {
	int nxt, to, w, f;
}e[40010];

void add_edge (int from, int to, int flw, int val) {
	e[++cnt].nxt = head[from];
	e[cnt].to = to;
	e[cnt].f = flw;
	e[cnt].w = val;
	head[from] = cnt;
}

void add_len (int u, int v, int f, int w) {
	add_edge (u, v, f, +w);
	add_edge (v, u, 0, -w);
}

int _head[210]; edge _e[40010];
int n, m, numA[110], numB[110], cost[110][110];

int A (int x) {return n * 0 + x;}
int B (int x) {return n * 1 + x;}

queue <int> q;
int dis[210], vis[210], flow[210];
int pre_edge[210], pre_node[210];

bool can_use (int u, int v, int i, int type) {
	if (type == +1) return dis[v] > dis[u] + e[i].w;
	if (type == -1) return dis[v] < dis[u] + e[i].w;
}

int spfa (int s, int t, int type) {
	memset (vis, 0, sizeof (vis));
	memset (flow, 0x3f, sizeof (flow));
	if (type == +1) memset (dis, +0x3f, sizeof (dis));
	if (type == -1) memset (dis, -0x3f, sizeof (dis));
	vis[s] = true; dis[s] = 0; q.push (s);
	while (!q.empty ()) {
		int u = q.front (); q.pop ();
		for (int i = head[u]; ~i; i = e[i].nxt) {
			int v = e[i].to;
			if (can_use (u, v, i, type) && e[i].f) {
				dis[v] = dis[u] + e[i].w;
				flow[v] = min (flow[u], e[i].f);
				pre_edge[v] = i;
				pre_node[v] = u;
				if (!vis[v]) {
					vis[v] = true;
					q.push (v);
				}
			}
		}
		vis[u] = false;
	}
	return flow[t] != INF;
}

int MCMF (int s, int t, int type) {
	int cost = 0;
	while (spfa (s, t, type)) {
		cost += dis[t] * flow[t];
		int u = t;
		while (u != s) {
			e[pre_edge[u] ^ 0].f -= flow[t];
			e[pre_edge[u] ^ 1].f += flow[t];
			u = pre_node[u];
		} 
	}
	return cost;
}

int main () {
	memset (head, -1, sizeof (head));
	cin >> n >> m;
	int s = n + m + 1;
	int t = n + m + 2;
	for (int i = 1; i <= n; ++i) {cin >> numA[i]; add_len (s, A (i), numA[i], 0);}
	for (int i = 1; i <= m; ++i) {cin >> numB[i]; add_len (B (i), t, numB[i], 0);}
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			cin >> cost[i][j];
			add_len (A (i), B (j), INF, cost[i][j]);
		}
	}
	memcpy (_e, e, sizeof (e)); memcpy (_head, head, sizeof (head));
	cout << MCMF (s, t, +1) << endl;
	memcpy (e, _e, sizeof (e)); memcpy (head, _head, sizeof (head));
	cout << MCMF (s, t, -1) << endl;
}

posted @ 2019-03-08 08:22  maomao9173  阅读(90)  评论(0编辑  收藏  举报