http://www.lydsy.com/JudgeOnline/problem.php?id=1711
源点连向食物流量为1,食物连向人流量为1,把人拆点限流,人连向饮料流量为1
饮料连向汇点流量为1,然后,最大流
#include<cstdio> #include<queue> #include<cstring> #include<algorithm> std::queue<int>que; #define INF 0x7fffffff const int maxn = 30007; inline int read() { int x=0; char c=getchar(); while(c<'0'||c>'9')c=getchar(); while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar(); return x; } int n,f,d,S,T,src,decc; struct node{ int v,next,flow; }edge[maxn];int head[maxn],num=1,cur[maxn],lev[maxn]; void add_edge(int u,int v,int w) { edge[++num].v=v;edge[num].next=head[u];head[u]=num; edge[num].flow=w; } bool bfs() { while(!que.empty()) que.pop(); std::memset(lev,-1,sizeof lev); memcpy(cur,head,sizeof head); lev[src]=0; que.push(src);int now; while(!que.empty()) { now=que.front();que.pop(); for(int i=head[now];i;i=edge[i].next) { int v=edge[i].v; if(lev[v]==-1&&edge[i].flow>0) { lev[v]=lev[now]+1; if(v==decc)return true; que.push(v); } } } return false; } int dfs(int now,int flow) { if(now==decc)return flow; int rest=0,delta; for(int &i=cur[now];i;i=edge[i].next) { int v=edge[i].v; if(lev[v]==lev[now]+1&&edge[i].flow>0) { delta=dfs(v,std::min(flow-rest,edge[i].flow)); if(delta) { edge[i].flow-=delta; edge[i^1].flow+=delta; rest+=delta;if(rest==flow)break; } } } if(rest==flow)lev[now]=-1;//满流 return rest; } int Dinic() { int ans=0; while(bfs()) ans+=dfs(src,INF); return ans; } inline void add(int a,int b,int flow) { add_edge(a,b,flow);add_edge(b,a,0); } int main() { n=read(),f=read(),d=read(); src=0;decc=f+n+n+d+1; for(int a,b,po,i=1;i<=n;++i) { a=read(),b=read(); for(int j=1;j<=a;++j) po=read(),add(po,f+i,1); add(f+i,f+n+i,1); for(int j=1;j<=b;++j) po=read(),add(f+n+i,f+n+n+po,1); } for(int i=1;i<=f;++i)add(src,i,1); for(int i=f+n+n+1;i<=f+n+n+d;++i)add(i,decc,INF); printf("%d ",Dinic()); return 0; }