POJ-3281 Dining(最大流)


设容量为1,流量为0的边为edge.
用0表示源点,从零到每个食物之间连上edge,在从食物到相应的牛上连上edge,再从第i个牛到第i个牛上连上edge,在从牛到饮料上连上edge,从饮料到汇点连上edge.
食物标记:1-f;
第一次n头牛f+1, f+n;
第二次n头牛f+n+1, f+2*n;
饮料:f+2*n+1, f+2*n+d;
汇点:f+2*n+d+1;

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <stack>
#include <queue> 
#define maxn 605 
#define INF 1e9
typedef long long ll;

using namespace std;
struct Edge{
    Edge(){
    }
    Edge(int a, int b, int c, int d){
        from = a;
        to = b;
        cap = c;
        flow = d;
    }
    int from, to, cap, flow;
};
vector<Edge> edge;
vector<int> v[maxn];
int p[maxn], a[maxn], n, f, d;
void Addedge(int from, int to){

    edge.push_back(Edge(from, to, 1, 0));
    edge.push_back(Edge(to, from, 0, 0));
    int dd = edge.size();
    v[from].push_back(dd-2);
    v[to].push_back(dd-1);
}
void Init(){

    edge.clear();
    for(int i = 0; i < maxn; i++)
     v[i].clear(); 
    for(int i = 1; i <= n; i++){
        int k1, k2, a;
        scanf("%d%d", &k1, &k2);
        for(int j = 1; j <= k1; j++){
            scanf("%d", &a);
            Addedge(a, i+f);
        }
        for(int j = 1; j <= k2; j++){
            scanf("%d", &a);
            Addedge(f+n+i, f+2*n+a);
        }
    }
    for(int i = 1; i <= f; i++){
        Addedge(0, i);
    }
    for(int i = 1; i <= d; i++){
        Addedge(f+2*n+i, f+2*n+d+1);
    }
    for(int i = 1; i <= n; i++){
        Addedge(i+f, i+f+n);
    }
}
int MaxFlow(){

    int e = f + 2 * n + d + 1;
    int ans = 0;
    while(1){

        memset(a, 0, sizeof(a));
        a[0] = INF;
        queue<int> q;
        q.push(0);
        while(!q.empty()){

            int k = q.front();
            q.pop();
            for(int i = 0; i < v[k].size(); i++){
                Edge &e = edge[v[k][i]];
                if(a[e.to] == 0 && e.cap > e.flow){
                    a[e.to] = min(a[k], e.cap - e.flow);
                    q.push(e.to);
                    p[e.to] = v[k][i];
                }
            }
        }
        if(a[e] == 0)
          break;
        ans += a[e];
        for(int i = e; i != 0; i = edge[p[i]].from){
            edge[p[i]].flow += 1;
            edge[p[i]^1].flow -= 1;
        }
    }
    return ans;
}
int main(){

//  freopen("in.txt", "r", stdin);
    while(scanf("%d%d%d",&n, &f, &d) == 3){
        Init();
        cout << MaxFlow() << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值