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 }

 

posted @ 2013-01-23 17:54  silver__bullet  阅读(203)  评论(0编辑  收藏  举报