题意:有f种菜,d种饮品,每个牛有喜欢的一些菜和饮品,每种菜只能被选一次,饮品一样,问最多能使多少头牛享受自己喜欢的饮品和菜
分析:建边的时候,把牛拆成两个点,出和入
1,源点向每种菜流量为1
2,每种菜连所有喜欢这道菜的牛的入点,流量1
3,每头牛的入点和出点,流量为1
4,每头牛的出点连所有它喜欢的饮品,流量为1
5,每种饮品连汇点,流量为1
然后最大流是答案,这个题一定要拆点,因为一头牛只吃一次
注:模板采用的是LRJ大白书上的模板(其实这题和HDU 4292是一样的)
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <string> #include <stack> #include <vector> #include <map> #include <queue> #include <algorithm> #include <utility> using namespace std; typedef long long LL; const int maxn=4e2+5; const int INF=0x3f3f3f3f; struct Edge { int from,to,cap,flow; Edge(int u,int v,int c,int d):from(u),to(v),cap(c),flow(d) {} }; struct dinic { int s,t; vector<Edge>edges; vector<int>G[maxn]; int d[maxn]; int cur[maxn]; bool vis[maxn]; void init(){ edges.clear(); for(int i=0;i<maxn;++i) G[i].clear(); } bool bfs() { memset(vis,0,sizeof(vis)); queue<int>q; q.push(s); d[s]=0; vis[s]=1; while(!q.empty()) { int x=q.front(); q.pop(); for(int i=0; i<G[x].size(); i++) { Edge &e= edges[G[x][i]]; if(!vis[e.to]&&e.cap>e.flow) { vis[e.to]=1; d[e.to]=d[x]+1; q.push(e.to); } } } return vis[t]; } int dfs(int x,int a) { if(x==t||a==0)return a; int flow=0,f; for(int &i=cur[x]; i<G[x].size(); i++) { Edge &e=edges[G[x][i]]; if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))) { e.flow+=f; edges[G[x][i]^1].flow-=f; flow+=f; a-=f; if(a==0)break; } } return flow; } int maxflow(int s,int t) { this->s=s; this->t=t; int flow=0; while(bfs()) { memset(cur,0,sizeof(cur)); flow+=dfs(s,INF); } return flow; } void addedge(int u,int v,int c) { Edge x(u,v,c,0),y(v,u,0,0); edges.push_back(x); edges.push_back(y); int l=edges.size(); G[u].push_back(l-2); G[v].push_back(l-1); } }solve; int main() { int n,f,d; while(~scanf("%d%d%d",&n,&f,&d)){ solve.init(); for(int i=1;i<=n;++i){ int k1,k2; scanf("%d%d",&k1,&k2); for(int j=0;j<k1;++j){ int u;scanf("%d",&u); solve.addedge(u,i+f,1); } for(int j=0;j<k2;++j){ int v;scanf("%d",&v); solve.addedge(n+f+d+i,v+n+f,1); } } int s=0,t=2*n+f+d+1; for(int i=1;i<=n;++i)solve.addedge(i+f,i+n+f+d,1); for(int i=1;i<=f;++i)solve.addedge(s,i,1); for(int i=n+f+1;i<=n+f+d;++i)solve.addedge(i,t,1); printf("%d ",solve.maxflow(s,t)); } return 0; }