标签:
把牛拆成两个点i1和i2。从喜欢的食物到i1、i1到i2、i2到喜欢的饮料分别连边,容量都为1。再从源点到所有食物、所有饮料到汇点连边,容量同样为1。神解。原理很明显。全过程自己打的。第二道最大流。
-----------------------------------------------------------------------------------------
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
const int inf=0x3f3f3f3f;
const int nmax=405;
int read(){
int x=0,f=1;char c=getchar();
while(!isdigit(c)){
if(c==‘-‘) f=-1;
c=getchar();
}
while(isdigit(c)){
x=x*10+c-‘0‘;
c=getchar();
}
return x*f;
}
struct edge{
int to,cap;
edge *next,*rev;
};
edge e[400000];
int d[nmax],cnt[nmax];
edge *p[nmax],*head[nmax],*cur[nmax],*pt;
void add(int u,int v,int d){
pt->to=v;
pt->cap=d;
pt->next=head[u];
head[u]=pt++;
}
void adde(int u,int v,int d){
add(u,v,d);
add(v,u,0);
head[u]->rev=head[v];
head[v]->rev=head[u];
}
int maxflow(int s,int t,int n){
clr(cnt,0);cnt[0]=n;
clr(d,0);
int x=s,a=inf,flow=0;
while(d[s]<n){
edge *ee;
for(ee=cur[x];ee;ee=ee->next){
if(ee->cap>0&&d[ee->to]+1==d[x])
break;
}
if(ee){
p[ee->to]=cur[x]=ee;
x=ee->to;
a=min(ee->cap,a);
if(x==t){
while(x!=s){
p[x]->cap-=a;
p[x]->rev->cap+=a;
x=p[x]->rev->to;
}
flow+=a;
a=inf;
}
}else{
if(--cnt[d[x]]==0) break;
d[x]=n;//差了这一句!!!
for(ee=head[x];ee;ee=ee->next){
if(ee->cap>0&&d[ee->to]+1<d[x]){
d[x]=d[ee->to]+1;
cur[x]=ee;
}
}
cnt[d[x]]++;
if(x!=s) x=p[x]->rev->to;
}
}
return flow;
}
int main(){
int N=read(),F=read(),D=read();
int s=0,t=F+N+N+D+1;
pt=e;clr(head,0);
rep(i,F) adde(s,i,1);
rep(i,N) adde(F+i,F+N+i,1);
rep(i,D) adde(F+N+N+i,t,1);
rep(i,N){
int tmp=read(),tmp1=read();
rep(j,tmp) adde(read(),F+i,1);
rep(j,tmp1) adde(F+N+i,F+N+N+read(),1);
}
/*rep(i,t){
for(edge*ee=head[i];ee;ee=ee->next)
printf("%d %d\n",ee->to,ee->cap);
}*/
printf("%d\n",maxflow(s,t,t+1));
return 0;
}
-----------------------------------------------------------------------------------------
1711: [Usaco2007 Open]Dingin吃饭
Time Limit: 5 Sec Memory Limit: 64 MB
Submit: 678 Solved: 347
[Submit][Status][Discuss]
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} 中选
Sample Output
3
输出解释:
一个方案是:
Cow 1: 不吃
Cow 2: 食品 #2, 饮料 #2
Cow 3: 食品 #1, 饮料 #1
Cow 4: 食品 #3, 饮料 #3
用鸽笼定理可以推出没有更好的解 (一共只有3总食品和饮料).当然,别的数据会更难.
HINT
Source
[Submit][Status][Discuss]bzoj1711:ISAP
标签:
原文地址:http://www.cnblogs.com/fighting-to-the-end/p/5111238.html