写了一周网络流,今天校内小测了一发,就会两道题第二题还写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 }