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;
}

也当作模板吧。。

原文地址:https://www.cnblogs.com/louzhang/p/2634457.html