【bzoj1711/Usaco2007 Open】Dining吃饭——网络流
Description
农夫JOHN为牛们做了很好的食品,但是牛吃饭很挑食. 每一头牛只喜欢吃一些食品和饮料而别的一概不吃.虽然他不一定能把所有牛喂饱,他还是想让尽可能多的牛吃到他们喜欢的食品和饮料. 农夫JOHN做了F (1 <= F <= 100) 种食品并准备了D (1 <= D <= 100) 种饮料. 他的N (1 <= N <= 100)头牛都以决定了是否愿意吃某种食物和喝某种饮料. 农夫JOHN想给每一头牛一种食品和一种饮料,使得尽可能多的牛得到喜欢的食物和饮料. 每一件食物和饮料只能由一头牛来用. 例如如果食物2被一头牛吃掉了,没有别的牛能吃食物2.
Input
* 第一行: 三个数: N, F, 和 D
* 第2..N+1行: 每一行由两个数开始F_i 和 D_i, 分别是第i 头牛可以吃的食品数和可以喝的饮料数.下F_i个整数是第i头牛可以吃的食品号,再下面的D_i个整数是第i头牛可以喝的饮料号码.
Output
* 第一行: 一个整数,最多可以喂饱的牛数.
Sample Input
4 3 3
2 2 1 2 3 1
2 2 2 3 1 2
2 2 1 3 1 2
2 1 1 3 3
输入解释:
牛 1: 食品从 {1,2}, 饮料从 {1,2} 中选
牛 2: 食品从 {2,3}, 饮料从 {1,2} 中选
牛 3: 食品从 {1,3}, 饮料从 {1,2} 中选
牛 4: 食品从 {1,3}, 饮料从 {3} 中选
2 2 1 2 3 1
2 2 2 3 1 2
2 2 1 3 1 2
2 1 1 3 3
输入解释:
牛 1: 食品从 {1,2}, 饮料从 {1,2} 中选
牛 2: 食品从 {2,3}, 饮料从 {1,2} 中选
牛 3: 食品从 {1,3}, 饮料从 {1,2} 中选
牛 4: 食品从 {1,3}, 饮料从 {3} 中选
Sample Output
3
听说是三分图啊???就是从源向食物连一条权值为1的边,从饮料向汇连一条权值为1的边,将一头牛x拆成两个点x和x',从该牛能吃的食物向x和x'向能喝的饮料连边,权值也为1。然后跑一遍最大流即可。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 const int N=105,inf=0x3f3f3f3f; 5 long long an=0; 6 int n,D,F,T,tot=1,m=100; 7 int cur[N*4],first[N*4],d[N*4],q[N*4]; 8 struct node{ 9 int ne,to,w; 10 }e[500500]; 11 int read(){ 12 int ans=0,f=1;char c=getchar(); 13 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 14 while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();} 15 return ans*f; 16 } 17 void ins(int u,int v,int w){ 18 e[++tot]=(node){first[u],v,w};first[u]=tot; 19 e[++tot]=(node){first[v],u,0};first[v]=tot; 20 } 21 bool bfs(){ 22 memset(d,-1,sizeof(d));d[0]=0;q[0]=0; 23 int h=0,t=1; 24 while(h!=t){ 25 int x=q[h++];if(h>=400)h=0; 26 for(int i=first[x];i;i=e[i].ne){ 27 int to=e[i].to; 28 if(d[to]==-1&&e[i].w>0){ 29 d[to]=d[x]+1; 30 q[t++]=to;if(t>=400)t=0; 31 } 32 } 33 } 34 if(d[T]==-1)return 0; 35 return 1; 36 } 37 int dfs(int x,int a){ 38 if(x==T||!a)return a; 39 int flow=0,f; 40 for(int &i=cur[x];i;i=e[i].ne){ 41 int to=e[i].to; 42 if(d[to]==d[x]+1&&(f=dfs(to,std::min(e[i].w,a)))>0){ 43 e[i].w-=f; 44 e[i^1].w+=f; 45 flow+=f; 46 a-=f; 47 if(!a)break; 48 } 49 } 50 return flow; 51 } 52 int main(){ 53 n=read();F=read();D=read(); 54 T=4*m+1; 55 for(int i=1;i<=F;i++)ins(0,2*m+i,1); 56 for(int i=1;i<=D;i++)ins(3*m+i,T,1); 57 for(int i=1;i<=n;i++)ins(i,i+m,1); 58 for(int i=1,d,f;i<=n;i++){ 59 f=read();d=read();int a; 60 while(f--)a=read(),ins(2*m+a,i,1); 61 while(d--)a=read(),ins(m+i,3*m+a,1); 62 } 63 while(bfs()){ 64 for(int i=0;i<=T;i++)cur[i]=first[i]; 65 an+=dfs(0,inf); 66 } 67 printf("%lld",an); 68 return 0; 69 }