POJ 1149 PIGS 最大流

第一次做网络流,看着教材里面的题解做的= =

用的是Ford,应该是最好理解的把,就是不断的找有没有从源点到汇点的增广路然后更新。

建图真是难啊,而且感觉细节要注意的地方比较多,一开始没有考虑反向弧,WA了两发,sad...

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
#include <string>
#include <iostream>
#include <map>
#include <cstdlib>
#include <list>
#include <set>
#include <queue>
#include <stack>

using namespace std;

typedef long long LL;
const int INF = INT_MAX / 4;
const int maxn = 305;
const int maxm = 3005;
int n,m,s,t;
int A[maxn],K[maxn][maxm],B[maxn];    //A为每个顾客有的钥匙数量,K为钥匙的类型,B为顾客的需求
int P[maxm],firstp[maxm];    //猪圈中猪的数量,每个猪圈的第一个客户
int dist[maxn][maxn];

void input() {
    for(int i = 1;i <= m;i++) {
        scanf("%d",&P[i]);
    }
    for(int i = 1;i <= n;i++) {
        scanf("%d",&A[i]);
        for(int j = 1;j <= A[i];j++) {
            scanf("%d",&K[i][j]);
        }
        scanf("%d",&B[i]);
    }
}

void init() {
    s = 0; t = n + 1;
    memset(firstp,0,sizeof(firstp));
    memset(dist,0,sizeof(dist));
    for(int i = 1;i <= n;i++) {
        for(int j = 1;j <= A[i];j++) {
            if(firstp[K[i][j]] == 0) {
                firstp[K[i][j]] = i;
                dist[s][i] += P[K[i][j]];
            }
            else {
                dist[firstp[K[i][j]]][i] = INF;
                firstp[K[i][j]] = i;
            }
        }
        dist[i][t] = B[i];
    }
}

int flow[maxn][maxn];   //流量
int alpha[maxn],pre[maxn];      //每个点的可改进量和每个点的前驱
int q[maxn],qs,qe;      //队列

//Ford-Fulkerson
void solve() {
    memset(flow,0,sizeof(flow));
    alpha[s] = INF;
    while(1) {
        //初始化标号
        for(int i = 1;i <= t;i++) pre[i] = -2;
        pre[s] = -1;
        //初始化队列,源点入列
        qs = 0; qe = 1;
        q[qs] = s;
        //标号过程
        while(qs < qe && pre[t] == -2) {    //终点没有被标号并且队列非空
            int v = q[qs]; qs++;
            //printf("now v is %d
",v);
            for(int i = 1;i <= t;i++) {
                //如果目标点没有被标号并且还有残余流量
                if(pre[i] == -2 && dist[v][i] - flow[v][i] != 0) {
                    pre[i] = v;
                    alpha[i] = min(alpha[v],dist[v][i] - flow[v][i]);
                    q[qe++] = i;
                }
            }
        }
        //没有找到到汇点的增广路,退出
        if(pre[t] == -2) {
            break;
        }
        //逆向更新
        int aval = alpha[t];
        for(int i = t;pre[i] != -1;i = pre[i]) {
            flow[pre[i]][i] += aval;
            flow[i][pre[i]] = -flow[pre[i]][i];
        }
    }
    //统计流量
    int ans = 0;
    for(int i = 1;i <= n;i++) {
        ans += flow[i][t];
    }
    printf("%d
",ans);
}

int main() {
    while(scanf("%d%d",&m,&n) != EOF) {
        input();
        init();
        solve();
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/rolight/p/3868116.html