POJ 3281 Dining

农夫为他的 N (1 ≤ N ≤ 100) 牛准备了 F (1 ≤ F ≤ 100)种食物和 D (1 ≤ D ≤ 100) 种饮料。每头牛都有各自喜欢的食物和饮料,而每种食物或饮料只能分配给一头牛。最多能有多少头牛可以同时得到喜欢的食物和饮料?

Input

第一行输入三个整数N, F, D
接下来n行,每行先输入两个整数 Fi 和 Di,分别表示编号为 i 的牛喜欢的食物和饮料的数量,接下来的Fi个整数表示第i头牛喜欢的食物的编号,最后Di个整数表示第i头牛喜欢的饮料的编号。

Output

输出同时得到喜欢的食物和饮料的牛的数量的最大值。

Sample Input

4 3 3
2 2 1 2 3 1
2 2 2 3 1 2
2 2 1 3 1 2
2 1 1 3 3

Sample Output

3
一开始建图我就建错了
源点 牛 食物 饮料 汇点
这样是不对的 因为这样让牛能喝的饮料数变多了
应该是
源点 食物 牛 牛 饮料 汇点
牛和牛是同一头牛 ,因为这样可以保证牛的通过量只能为1 这就是所谓的拆点吧
#include<iostream>
#include<queue>
#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=500;
const int inf=0x3f3f3f;
int N;
int depth[maxn];
int a[maxn][maxn];
bool bfs(int s,int e)
{
    queue<int>q;
    memset(depth,-1,sizeof(depth));
    depth[s]=0;
    q.push(s);
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        for(int i=1;i<=N;i++)
        {
            if(depth[i]==-1&&a[now][i])
            {
                depth[i]=depth[now]+1;
                q.push(i);
            }
        }
    }
    return depth[e]>0;
 } 
 int dfs(int now,int e,int nowflow)
 {
     if(now==N) return nowflow;
     
     int findflow=0;
     for(int i=1;i<=N;i++)
     {
         if(a[now][i]&&depth[i]==depth[now]+1)
         {
             findflow=dfs(i,e,min(nowflow,a[now][i]));
             if(findflow)
             {
                 a[now][i]-=findflow;
                 a[i][now]+=findflow;
                 return findflow;
             }
         }
     }
     if(!findflow) depth[now]=-2;
     return false;
 }
 int dinic(int s,int e)
 {
     int maxflow=0;
     while(bfs(s,e))
     maxflow+=dfs(s,e,1<<20);
     
     return maxflow;
 }
 int main()
 {
     int n,f,d;
     while(scanf("%d%d%d",&n,&f,&d)!=EOF)
     {
         memset(a,0,sizeof(a));
         N=f+d+2*n+2;
         for(int i=1;i<=f;i++)
         a[1][i+1]=1;
         for(int i=1;i<=n;i++)
         a[i+f+1][i+f+1+n]=1;
         for(int i=1;i<=d;i++)
         a[i+1+f+2*n][2+f+2*n+d]=1;
         for(int i=1;i<=n;i++)
         {
             int t1,t2,t3;
             cin>>t1>>t2;
             for(int j=1;j<=t1;j++)
             {
                 cin>>t3;
                 a[t3+1][i+1+f]=1;
             }
             for(int j=1;j<=t2;j++)
             {
                 cin>>t3;
                 a[i+1+f+n][t3+1+f+2*n]=1;
             }
         }
         cout<<dinic(1,N)<<endl;
     }
 }

 

 
posted @ 2018-08-21 16:41  踩在浪花上  阅读(146)  评论(0编辑  收藏  举报