题意:
有一些食物和饮料...有一些牛..每头牛有自己喜欢的若干食物和饮料..对于一头牛来说只要吃到了任意一个自己喜欢的食物和任意一个自己喜欢的饮料..这头牛就会很满意..每个食物、每个饮料至多被一头牛吃...问最多能使多少头牛满意...
题解:
开始题目看错了..看成每头牛要吃掉自己喜欢的所有食物和饮料..然后跪了..
还是很简单的..因为一头牛要吃食物又要吃饮料..所以把牛拆点..用容量为1的边连起来..食物的一半连它喜欢的食物..饮料的一半连它喜欢的饮料..边的容量都是1..这样保证了每头牛至多选择一次..并且成功选择必定会带走一个食物和一个饮料...加上超级源点和汇点..跑最大流就是结果了....
总结:
这类问题的特点是求最大or最小值..并且资源的拥有有互斥和数量限制....
PS..题外话...如果每头牛喜欢的食物和饮料只有一种..就可以用二分图匹配..否则没办法....
Program:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
#define MAXN 1000005
#define MAXM 1000005
#define oo 1000000007
#define ll long long
using namespace std;
struct Dinic
{
struct node
{
int x,y,c,next;
}line[MAXM];
int Lnum,_next[MAXN],dis[MAXN];
void initial(int n)
{
for (int i=0;i<=n;i++) _next[i]=-1;
Lnum=-1;
}
void addline(int x,int y,int c)
{
line[++Lnum].next=_next[x],_next[x]=Lnum;
line[Lnum].x=x,line[Lnum].y=y,line[Lnum].c=c;
line[++Lnum].next=_next[y],_next[y]=Lnum;
line[Lnum].x=y,line[Lnum].y=x,line[Lnum].c=0;
}
bool BFS(int s,int e)
{
queue<int> Q;
while (!Q.empty()) Q.pop();
memset(dis,0,sizeof(dis));
dis[s]=1;
Q.push(s);
while (!Q.empty())
{
int h,k;
h=Q.front(),Q.pop();
if (h==e) return dis[e];
for (k=_next[h];k!=-1;k=line[k].next)
if (line[k].c && !dis[line[k].y])
dis[line[k].y]=dis[h]+1,Q.push(line[k].y);
}
return false;
}
int dfs(int x,int flow,int e)
{
if (x==e) return flow;
int temp,cost=0;
for (int k=_next[x];k!=-1;k=line[k].next)
if (line[k].c && dis[line[k].y]==dis[x]+1)
{
temp=dfs(line[k].y,min(flow-cost,line[k].c),e);
if (temp)
{
line[k].c-=temp,line[k^1].c+=temp;
cost+=temp;
if (flow==cost) return cost;
}else dis[line[k].y]=-1;
}
return cost;
}
int MaxFlow(int s,int e)
{
int MaxFlow=0;
while (BFS(s,e)) MaxFlow+=dfs(s,oo,e);
return MaxFlow;
}
}T;
int main()
{
int n,A,B,s,e,i,x,Ai,Bi;
scanf("%d%d%d",&n,&A,&B);
s=n*2+A+B+1,e=s+1;
T.initial(e);
for (i=1;i<=A;i++) T.addline(s,i+2*n,1);
for (i=1;i<=B;i++) T.addline(i+2*n+A,e,1);
for (i=0;i<n;i++)
{
scanf("%d%d",&Ai,&Bi);
T.addline(i<<1,i<<1|1,1);
while (Ai--)
{
scanf("%d",&x);
T.addline(x+2*n,i<<1,1);
}
while (Bi--)
{
scanf("%d",&x);
T.addline(i<<1|1,x+2*n+A,1);
}
}
printf("%d\n",T.MaxFlow(s,e));
return 0;
}