POJ 3281 Dining

题目大意:

有N只牛,每只牛都偏爱吃一种食和饮料,现在有F种食物,D种饮料,现在想要给尽可能多的牛一份美餐。
 
输入数据:
一个N代表N只牛, F代表有F种食物, D代表有D种饮料。
接下来N行,
第i行代表,第i只牛,每行前两个数,Fi, Di 分别代表第i只牛喜欢的食物有Fi种,喜欢的饮料有Di种。
然后是Fi个数字,和Di个数字。
===========================================================================================
把牛拆开,  使得牛与牛之间的流量为 1, 虚拟一个源点 虚拟一个汇点。
 
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long LL;
const int INF = 1e9+7;
const int maxn = 5005;
const int MOD = 1e9+7;
int n, F, D, k;
int Layer[maxn], Head[maxn];
struct Edge
{
    int from, to, flow;
    int next;
} edge[maxn*2];

void AddEdge(int from,int to,int flow)
{
    edge[k].from = from;
    edge[k].to = to;
    edge[k].flow = flow;
    edge[k].next = Head[from];
    Head[from] = k ++;

    swap(from, to);

    edge[k].from = from;
    edge[k].to = to;
    edge[k].flow = 0;
    edge[k].next = Head[from];
    Head[from] = k ++;
}

bool BfsLayer(int Star,int End)
{
    queue<int> Q;
    memset(Layer, -1, sizeof(Layer));
    Layer[Star] = 1;
    Q.push(Star);

    while( Q.size() )
    {
        int s = Q.front(), to;
        Q.pop();
        if(s == End)
            return true;

        for(int i=Head[s]; i != -1; i=edge[i].next)
        {
            to = edge[i].to;
            if( Layer[to] == -1 && edge[i].flow)
            {
                Q.push(to);
                Layer[to] = Layer[s] + 1;
            }
        }
    }
    return false;
}

int DFS(int Star,int End,int MaxFlow)
{
    if(Star == End)///如果已经到达汇点
        return MaxFlow;

    int sFlow = 0;///这点到达汇点的流量
    for(int i=Head[Star]; i != -1; i=edge[i].next)
    {
        int to = edge[i].to;
        int flow = edge[i].flow;

        if(Layer[Star] + 1 == Layer[to] && flow)
        {
            flow = min(MaxFlow-sFlow, flow);/// (到达Star的最大流量 - 从Star流出的流量,路径上最大限制的流量) = 到达下一个点的最大流量
            flow = DFS(to, End, flow);///返回to可以到达汇点的最大流量

            sFlow += flow;
            edge[i].flow -= flow;
            edge[i^1].flow += flow;

            if(sFlow == MaxFlow)///改点已经不能再分配出其他流量了。
                break;
        }
    }
    if(sFlow == 0)///这个点已经不能再向汇点输送流量了。
        Layer[Star] = -1;

    return sFlow;
}

int Dinic(int Star,int End)
{
    int ans = 0;
    while( BfsLayer(Star, End) )
    {
        ans += DFS(Star, End, INF);
    }
    return ans;
}


int main()
{
    while(cin >> n >> F >> D)
    {
        int Fi, Di, f, d;
        int N1=F, N2=N1+n, Ds=N2+n, start=Ds+D+1, End=start+1;

        k = 0;
        memset(Head, -1, sizeof(Head));

        for(int i=1; i<=n; i++)
        {
            cin >> Fi >> Di;

            AddEdge(N1+i, N2+i, 1);///把牛拆点建图,建立牛一和牛二之间的联系

            for(int j=0; j<Fi; j++)
            {
                cin >> f;
                AddEdge(f, N1+i, 1);///建立食物和牛一之间的联系
            }

            for(int j=0; j<Di; j++)
            {
                cin >> d;
                AddEdge(N2+i, Ds+d, 1);///建立牛二和饮料之间的联系
            }
        }

        for(int i=1; i<=F; i++)
            AddEdge(start, i, 1);
        for(int i=1; i<=D; i++)
            AddEdge(Ds+i, End, 1);

        printf("%d\n", Dinic(start, End) );
    }
    return 0;
}

 

posted @ 2015-10-01 17:11  向前走丶不回首  阅读(146)  评论(0编辑  收藏  举报