写了一周网络流,今天校内小测了一发,就会两道题第二题还写GG了,真是惨2333.......

1.最大流求最大匹配

  A.bzoj 1711 Dining吃饭

  显然每头牛要和一种食物还有一种饮料匹配,但因为要匹配两种东西,所以直接用二分图最大匹配是做不了的,那么我们可以建三层,S向食物连边,食物向牛连边,牛拆点中间连边,然后在向饮料连边,饮料向T连边。边的容量都为一,这样每条S到T的路径都是一个三种东西的匹配,容量都为一保证了不会重。

  

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<queue>
 5 #include<cstring>
 6 #define inf 0x3f3f3f3f
 7 #define N 505
 8 #define M 1000005
 9 using namespace std;
10 int head[N],nxt[M],ver[M],tot,f[M];
11 void add(int a,int b,int c)
12 {
13     tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;f[tot]=c;
14     tot++;nxt[tot]=head[b];head[b]=tot;ver[tot]=a;f[tot]=0;
15 }
16 int S,T;
17 int ch[N];
18 int zeng(int a,int b)
19 {
20     if(a==T)return b;
21     int r=0;
22     for(int i=head[a];i&&b>r;i=nxt[i])
23     {
24         if(ch[ver[i]]==ch[a]+1&&f[i])
25         {
26             int t=zeng(ver[i],min(b-r,f[i]));
27             r+=t;f[i]-=t;f[i^1]+=t;
28         }
29     }
30     if(!r)ch[a]=-1;
31     return r;
32 }
33 bool tell()
34 {
35     memset(ch,-1,sizeof(ch));
36     ch[S]=0;
37     queue<int>q;
38     q.push(S);
39     while(!q.empty())
40     {
41         int tmp=q.front();q.pop();
42         for(int i=head[tmp];i;i=nxt[i])
43         {
44             if(f[i]&&ch[ver[i]]==-1)
45             {
46                 ch[ver[i]]=ch[tmp]+1;
47                 q.push(ver[i]);
48             }
49         }
50     }
51     return ch[T]!=-1;
52 }
53 int dinic()
54 {
55     int r=0,t;
56     while(tell())while(t=zeng(S,inf))r+=t;
57     return r;
58 }
59 int n,ff,d;
60 int main()
61 {
62    tot=1;
63    scanf("%d%d%d",&n,&ff,&d);
64    for(int i=1;i<=ff;i++)add(S,i,1);
65    for(int i=1;i<=n;i++)add(i+ff,i+ff+n,1);
66    S=0;T=2*n+ff+d+1;
67    int t1,t2;
68    for(int i=1;i<=n;i++)
69    {
70     scanf("%d%d",&t1,&t2);
71     int tmp;
72     for(int j=1;j<=t1;j++)
73     {
74         scanf("%d",&tmp);
75         add(tmp,i+ff,1);
76     }
77     for(int j=1;j<=t2;j++)
78     {
79         scanf("%d",&tmp);
80         add(i+ff+n,tmp+2*n+ff,1);
81     }
82    }
83    for(int i=1;i<=d;i++)add(i+ff+2*n,T,1);
84    printf("%d\n",dinic());
85    return 0;
86 }
View Code

相关文章: