poj_2516,最小费用最大流
http://poj.org/problem?id=2516
参考这篇博客写的。。。
http://www.cppblog.com/Icyflame/archive/2009/06/30/88941.html
这几天算是被网络流整死了,算法太复杂了,理解起来确实是难。。
2516
#include<cstdio> #include<cstring> const int inf = 10000000; const int maxn = 110; struct Edge{ int u, v, w, c, next; }e[maxn * maxn * 4]; int head[maxn], index; void init_edge(){ memset(head, -1, sizeof head); index = 0; } void _add_edge(int u, int v, int w, int c){ e[index].u = u, e[index].v = v; e[index].w = w, e[index].c = c; e[index].next = head[u]; head[u] = index ++; } void add_edge(int u, int v, int w, int c){ _add_edge(u, v, w, c); _add_edge(v, u, -w, 0); } int q[1000000 + 10]; int visit[maxn]; int dist[maxn]; int pre[maxn]; int s, t, n; bool spfa(){ int qs = 0, qe = 0; memset(visit, 0, sizeof visit); memset(pre, -1, sizeof pre); for(int i = s; i <= t; i ++) dist[i] = inf; q[qe++] = s; visit[s] = 1; dist[s] = 0; while(qs < qe){ int now = q[qs++]; visit[now] = 0; for(int i = head[now]; i + 1; i = e[i].next){ int v = e[i].v; if(!e[i].c) continue; if(dist[v] == inf || dist[now] + e[i].w < dist[v]){ dist[v] = dist[now] + e[i].w; pre[v] = i; if(!visit[v]){ visit[v] = 1; q[qe++] = v; } } } } return dist[t] != inf; } int min_cost(){ int cost = 0; while(spfa()){ int flow = inf; for(int i = pre[t]; i != -1; i = pre[e[i].u]) if(flow > e[i].c) flow = e[i].c; for(int i = pre[t]; i != -1; i = pre[e[i].u]){ e[i].c -= flow; e[i^1].c += flow; } cost += flow * dist[t]; } return cost; } int N, M, K; int need[maxn][maxn]; int supply[maxn][maxn]; int m[maxn][maxn][maxn]; int main(){ while(scanf("%d%d%d", &N, &M, &K), N||M||K){ for(int i = 1; i <= N; i ++){ for(int j = 1; j <= K; j ++){ int a; scanf("%d", &a); need[i][j] = a; } } for(int i = 1; i <= M; i ++){ for(int j = 1; j <= K; j ++){ int a; scanf("%d", &a); supply[i][j] = a; } } for(int i = 1; i <= K; i ++){ for(int j = 1; j <= N; j ++){ for(int k = 1; k <= M; k ++){ int a; scanf("%d", &a); m[i][j][k] = a; } } } n = N + M; s = 0, t = n + 1; int ans = 0; for(int k = 1; k <= K; k ++){ init_edge(); for(int i = 1; i <= M; i ++){ add_edge(s, i, 0, supply[i][k]); } for(int i = 1; i <= M; i ++){ for(int j = 1; j <= N; j ++){ add_edge(i, j + M, m[k][j][i], inf); } } for(int i = 1; i <= N; i ++){ add_edge(i + M, t, 0, need[i][k]); } ans += min_cost(); bool flag = 0; for(int i = 1 + M; i <= N + M; i ++){ for(int j = head[i]; j + 1; j = e[j].next){ int v = e[j].v; if(v == t && e[j].c > 0){ flag = true; break; } } if(flag) break; } if(flag){ ans = -1; break; } } printf("%d\n", ans); } return 0; }
也当作模板吧。。
posted on 2012-08-12 14:00 louzhang_swk 阅读(218) 评论(0) 编辑 收藏 举报