题目大意: 有n头牛,并且分别有f,d种食物和饮品。接下来是n行每行前两个数f1,d1分别是代表当前事食物和饮品的编号。求最大可能让牛得到喜欢的套餐。
思路:第一次才知道什么是拆点的问题,对于此题就是为了保证牛只吃一份套餐。然后是建图问题,我们可以让牛放在食物和饮料之间并将牛拆分,注意下标!。同时将Map[i][i+n]自己和自己相连。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> #define inf 0x3f3f3f3f using namespace std; int Map[1000][1000],s,e,l[10000]; int bfs() { memset(l,-1,sizeof(l)); l[s]=0; queue<int>q; while(!q.empty()) q.pop(); q.push(s); while(!q.empty()){ int v=q.front(); q.pop(); for(int i=1;i<=e;i++){ if(Map[v][i]&&l[i]==-1){ l[i]=l[v]+1; q.push(i); } } } return l[e]!=-1; } int dfs(int x,int f){ if(x==e||!f) return f; int tmp=0; for(int i=1;i<=e;i++){ if(Map[x][i]&&l[x]+1==l[i]){ int a=dfs(i,min(Map[x][i],f-tmp)); if(a>0){ Map[x][i]-=a; Map[i][x]+=a; tmp+=a; if(tmp==f) break; } } } if(tmp==0) l[x]=-1; return tmp; } int main(){ int n,f,d,i,j,k; while(~scanf("%d%d%d",&n,&f,&d)){ memset(Map,0,sizeof(Map)); s=0; int f1,d1; for(i=1;i<=n;++i){ scanf("%d%d",&f1,&d1); for(j=0;j<f1;j++){ scanf("%d",&k); Map[2*n+k][i]=1;//Map[i][2*n+k]=1; } for(j=0;j<d1;j++) { scanf("%d",&k); Map[n+i][2*n+f+k]=1; } Map[i][i+n]=1; } e=2*n+f+d+1; for(i=2*n+1;i<=2*n+f;++i) Map[0][i]=1; for(i=2*n+f+1;i<=2*n+f+d;i++) Map[i][e]=1; int ans=0; while(bfs()){ ans+=dfs(0,inf); } printf("%d\n",ans); } return 0; }