poj 3281 Dining
题意:有N头牛,F种食物,D种饮料,每头牛有自己喜欢的食物和饮料,每种食物/饮料只能被一头牛享用,每头牛只能享用一种饮料和一种食物,求最后能有几头牛享用到自己喜欢的食物或饮料。
解法:很容易想到建图方法,食物放左边,饮料放右边,牛放中间,然后按照给定的关系连边,但这里需要对牛拆点,如果不拆的话,比如有这样的两条链,s->食物1->牛1->饮料1->t,s->食物2->牛1->饮料2->t,这两条路都会被增广,从而出现错误,因为建图的时候并没有限制“每头牛只能享用一种饮料和一种食物”这个条件,拆点之后就有了限制。。。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define N 410 5 using namespace std; 6 const int inf=1<<30; 7 struct Edge{ 8 int u,v,c,next; 9 Edge(){} 10 Edge(int _u,int _v,int _c,int _next){ 11 u=_u;v=_v;c=_c;next=_next; 12 } 13 }edge[N*N]; 14 int head[N],cnt; 15 int h[N],gap[N]; 16 int n,source,sink; 17 void init(){ 18 memset(head,-1,sizeof(head)); 19 cnt=0; 20 } 21 void addedge(int u,int v,int c){ 22 edge[cnt]=Edge(u,v,c,head[u]);head[u]=cnt++; 23 } 24 int dfs(int u,int cost){ 25 if(u==sink)return cost; 26 int lv=cost,minh=n+1,d; 27 for(int k=head[u];k!=-1;k=edge[k].next){ 28 int v=edge[k].v,c=edge[k].c; 29 if(c>0){ 30 if(h[v]+1==h[u]){ 31 d=dfs(v,min(lv,c)); 32 edge[k].c-=d; 33 edge[k^1].c+=d; 34 lv-=d; 35 if(h[source]>=n+2)return cost-lv; 36 if(!lv)break; 37 } 38 minh=min(minh,h[v]); 39 } 40 } 41 if(lv==cost){ 42 --gap[h[u]]; 43 if(gap[h[u]]==0)h[source]=n+2; 44 h[u]=minh+1; 45 ++gap[h[u]]; 46 } 47 return cost-lv; 48 } 49 int sap(){ 50 memset(h,0,sizeof(h)); 51 memset(gap,0,sizeof(gap)); 52 gap[h[source]]=n+2; 53 int ans=0; 54 while(h[source]<n+2)ans+=dfs(source,inf); 55 return ans; 56 } 57 int main(){ 58 int nn,f,d; 59 while(~scanf("%d%d%d",&nn,&f,&d)){ 60 init(); 61 n=nn*2+f+d; 62 source=0;sink=n+1; 63 for(int i=1;i<=f;i++){ 64 addedge(source,i,1); 65 addedge(i,source,0); 66 } 67 for(int i=1;i<=d;i++){ 68 addedge(nn*2+f+i,sink,1); 69 addedge(sink,nn*2+f+i,0); 70 } 71 for(int i=1;i<=nn;i++){ 72 addedge(f+i,f+nn+i,1); 73 addedge(f+nn+i,f+i,0); 74 } 75 for(int i=1;i<=nn;i++){ 76 int a,b,c; 77 scanf("%d%d",&a,&b); 78 while(a--){ 79 scanf("%d",&c); 80 addedge(c,f+i,1); 81 addedge(f+i,c,0); 82 } 83 while(b--){ 84 scanf("%d",&c); 85 addedge(f+nn+i,f+nn*2+c,1); 86 addedge(f+nn*2+c,f+nn+i,0); 87 88 } 89 } 90 int ans=sap(); 91 printf("%d\n",ans); 92 } 93 return 0; 94 }