http://poj.org/problem?id=3281
注意:拆牛的时候左边牛标1右边标2,再左边标3右边标4,不是左边1-n,右边n+1-2*n
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int maxn=500+10;
const int inf=0x3f3f3f3f;
struct Edge{
int from,to,cap,flow;
Edge(int from,int to,int cap,int flow):from(from),to(to),cap(cap),flow(flow){}
};
struct EdmondsKarp{
int n,m;
vector<Edge> edges;
vector<int> G[maxn];
int a[maxn],p[maxn];
void init(int n){
this->n=n;
for(int i=0;i<n;i++)G[i].clear();
edges.clear();
}
void AddEdge(int from,int to,int cap){
edges.push_back(Edge(from,to,cap,0));
edges.push_back(Edge(to,from,0,0));
m=edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
int Maxflow(int s,int t){
int flow=0;
for(;;){
memset(a,0,sizeof(a));
queue<int> q;
q.push(s);
a[s]=inf;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<G[u].size();i++){
Edge& e=edges[G[u][i]];
if(!a[e.to]&&e.cap>e.flow){
a[e.to]=min(a[u],e.cap-e.flow);
p[e.to]=G[u][i];
q.push(e.to);
}
}
if(a[t])break;
}
if(!a[t])break;
for(int u=t;u!=s;u=edges[p[u]].from){
edges[p[u]].flow+=a[t];
edges[p[u]^1].flow-=a[t];
}
flow+=a[t];
}
return flow;
}
};
EdmondsKarp g;
int n,f,d;
int main(){
scanf("%d%d%d",&n,&f,&d);
g.init(f+d+2*n+2);
for(int i=1;i<=n;i++){
int s1,s2;
scanf("%d%d",&s1,&s2);
while(s1--){
int w;
scanf("%d",&w);
g.AddEdge(w,f+i*2-1,1);
}
while(s2--){
int w;
scanf("%d",&w);
g.AddEdge(f+i*2,f+n*2+w,1);
}
g.AddEdge(f+i*2-1,f+i*2,1);
}
int s=0,t=f+d+2*n+1;
for(int i=1;i<=f;i++){
g.AddEdge(s,i,1);
}
for(int i=1;i<=d;i++){
g.AddEdge(f+2*n+i,t,1);
}
int ans=g.Maxflow(s,t);
printf("%d\n",ans);
return 0;
}