题目链接:
https://www.luogu.com.cn/problem/P2891
本题和 洛谷 P1402 酒店之王https://www.luogu.com.cn/problem/P1402
和 洛谷 P1231 教辅的组成https://www.luogu.com.cn/problem/P1231
思路完全一致见https://blog.csdn.net/aiwo1376301646/article/details/104251335
算法:1:Dinic算法
思路:
1:拆点:把一头牛分开,分成牛A和牛B,在牛A与牛B之间连一条容量为1的边
2:把牛放在中间,食物和饮料放两边,然后就是一个裸的网络流
3:图解:
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=4e2+2,maxm=5e4+1;
int n,f,d,fi,di,a,s,t,tot=1,head[maxn],dep[maxn],ans;
struct edge
{
int to,next,w;
}e[maxm];
inline void addedge(int x,int y,int w)
{
e[++tot].to=y;
e[tot].w=w;
e[tot].next=head[x];
head[x]=tot;
}
inline bool bfs()
{
memset(dep,0,sizeof dep);
queue<int>q;
q.push(s);dep[s]=1;
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].to,w=e[i].w;
if(w&&!dep[y])
{
dep[y]=dep[x]+1;
q.push(y);
}
}
}
return dep[t];
}
inline int dfs(int x,int flow)
{
if(x==t)return flow;
int sum=0;
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].to,w=e[i].w;
if(w&&dep[y]==dep[x]+1)
{
int t=dfs(y,min(flow,w));
e[i].w-=t;e[i^1].w+=t;
flow-=t;sum+=t;
}
}
if(!sum)dep[x]=0;
return sum;
}
int main()
{
ios::sync_with_stdio(0);
scanf("%d %d %d",&n,&f,&d);
s=0,t=n+n+f+d+1;
for(int i=1;i<=n;i++)addedge(i,i+n,1),addedge(i+n,i,0);
for(int i=1;i<=f;i++)addedge(s,n+n+i,1),addedge(n+n+i,s,0);
for(int i=1;i<=d;i++)addedge(n+n+f+i,t,1),addedge(t,n+n+f+i,0);
for(int i=1;i<=n;i++)
{
scanf("%d %d",&fi,&di);
for(int j=1;j<=fi;j++)scanf("%d",&a),addedge(n+n+a,i,1),addedge(i,n+n+a,0);
for(int j=1;j<=di;j++)scanf("%d",&a),addedge(n+i,n+n+f+a,1),addedge(n+n+f+a,n+i,0);
}
while(bfs())ans+=dfs(s,2e9);
printf("%d\n",ans);
return 0;
}