基本算是裸的网络流,添加源点和汇点,然后源点跟牛相连,容量为1。然后Stall与汇点相连容量为1,然后对每条边进行连接,容量为1,然后就求最大流就行了
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<queue> using namespace std; const int inf=1<<29; const int maxn=500; const int maxm=maxn*maxn; int e,st,des,head[maxn],pnt[maxm],flow[maxm],nxt[maxm],level[maxn]; int n,m; queue<int> q; void AddEdge(int u,int v,int f) { pnt[e]=v;nxt[e]=head[u];flow[e]=f;head[u]=e++; pnt[e]=u;nxt[e]=head[v];flow[e]=0;head[v]=e++; } bool BFS() { memset(level,0,sizeof(level)); level[st]=1; q.push(st); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=nxt[i]) if(flow[i]&&!level[pnt[i]]) { level[pnt[i]]=level[u]+1; q.push(pnt[i]); } } return level[des]; } int DFS(int u,int maxf) { if(u==des||!maxf) return maxf; int f=0; for(int i=head[u];i!=-1;i=nxt[i]) if(flow[i]&&level[pnt[i]]==level[u]+1) { int t=DFS(pnt[i],min(flow[i],maxf-f)); if(t>0) { flow[i]-=t; flow[i^1]+=t; f+=t; if(maxf==f) break; } else level[pnt[i]]=0; } return f; } int maxflow() { int ans=0; while(BFS()) ans+=DFS(st,inf); return ans; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { e=st=0;des=n+m+1; memset(head,-1,sizeof(head)); for(int i=1;i<=n;i++) AddEdge(st,i,1); for(int i=1;i<=m;i++) AddEdge(n+i,des,1); for(int i=1;i<=n;i++) { int k; scanf("%d",&k); while(k--) { int s; scanf("%d",&s); AddEdge(i,n+s,1); } } printf("%d\n",maxflow()); } return 0; }