- 和过去的自己不期而遇
- 需要进行点边转化以限制1头牛至多只产生1的贡献
点击查看代码
#include <bits/stdc++.h>
using namespace std;
vector<int>a[1005],c[1005],h[1005];
int cur[1005],d[1005];
int s=0,t=1000;
queue<int>q;
int read1()
{char cc=getchar();while(!(cc>=48&&cc<=57)){if(cc=='-'){break;}cc=getchar();}bool f=false;int s=0;if(cc=='-'){f=true;}else{s=cc-48;}while(1){cc=getchar();if(cc>=48&&cc<=57){s=s*10+cc-48;}else{break;}}if(f==true){s=-s;}return s;
}
void add(int u,int v,int w)
{a[u].push_back(v);a[v].push_back(u);c[u].push_back(w);c[v].push_back(0);h[u].push_back(a[v].size()-1);h[v].push_back(a[u].size()-1);return;
}
bool bfs()
{memset(d,0,sizeof(d));while(!q.empty()){q.pop();}q.push(s);d[s]=1;while(!q.empty()){int n1=q.front();q.pop();for(int i=0;i<a[n1].size();i++){if(c[n1][i]!=0&&d[a[n1][i]]==0){d[a[n1][i]]=d[n1]+1;q.push(a[n1][i]);if(a[n1][i]==t){return true;}}}}return false;
}
int dinic(int n1,int flow)
{if(n1==t){return flow;}int rest=flow;for(int i=cur[n1];i<a[n1].size();i++){cur[n1]=i;if(c[n1][i]!=0&&d[a[n1][i]]==d[n1]+1){int k=dinic(a[n1][i],min(rest,c[n1][i]));if(k==0){d[a[n1][i]]=0;continue;}c[n1][i]-=k;c[a[n1][i]][h[n1][i]]+=k;rest-=k;if(rest==0){break;}}}return flow-rest;
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);int n,F,D;cin>>n>>F>>D;for(int i=1;i<=F;i++){add(s,i,1);}for(int i=1;i<=n;i++){add(F+i,F+n+i,1);}for(int i=1;i<=D;i++){add(F+2*n+i,t,1);}for(int i=1;i<=n;i++){int f=read1(),d=read1();for(int j=1;j<=f;j++){int w=read1();add(w,F+i,1);}for(int j=1;j<=d;j++){int w=read1();add(F+n+i,F+2*n+w,1);}}int ans=0,flow=0;while(bfs()){memset(cur,0,sizeof(cur));while(flow=dinic(s,INT_MAX)){ans+=flow;}}cout<<ans<<endl;return 0;
}
/*
图中的点有容量限制
每头牛只享用一种食物和一种饮料
*/