首页 > 代码库 > POJ 3281 Dining(网络最大流)
POJ 3281 Dining(网络最大流)
http://poj.org/problem?id=3281
Dining
Description Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she will consume no others. Farmer John has cooked fabulous meals for his cows, but he forgot to check his menu against their preferences. Although he might not be able to stuff everybody, he wants to give a complete meal of both food and drink to as many cows as possible. Farmer John has cooked F (1 ≤ F ≤ 100) types of foods and prepared D (1 ≤ D ≤ 100) types of drinks. Each of his N (1 ≤ N ≤ 100) cows has decided whether she is willing to eat a particular food or drink a particular drink. Farmer John must assign a food type and a drink type to each cow to maximize the number of cows who get both. Each dish or drink can only be consumed by one cow (i.e., once food type 2 is assigned to a cow, no other cow can be assigned food type 2). Input Line 1: Three space-separated integers: N, F, and D Lines 2..N+1: Each line i starts with a two integers Fi and Di, the number of dishes that cow i likes and the number of drinks that cow i likes. The next Fi integers denote the dishes that cow i will eat, and theDi integers following that denote the drinks that cow i will drink. Output Line 1: A single integer that is the maximum number of cows that can be fed both food and drink that conform to their wishes 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 Sample Output 3 Hint One way to satisfy three cows is: Cow 1: no meal Cow 2: Food #2, Drink #2 Cow 3: Food #1, Drink #1 Cow 4: Food #3, Drink #3 The pigeon-hole principle tells us we can do no better since there are only three kinds of food or drink. Other test data sets are more challenging, of course. Source USACO 2007 Open Gold |
被自己蠢哭,两个变量名手滑敲反居然WA了我4个小时。
题意:
有N头牛,F个食物,D个饮料。给出每头牛喜欢的食物和饮料的列表,要给每头牛配一个喜欢的食物和一个喜欢的饮料,每个食物和饮料只能配给一头牛,求最多能配多少牛。
分析:
看到匹配基本就想到是网络流了。
首先源点到每个食物连一条容量为1的边,这样确保每个食物只有1个,同理饮料到汇点连一条容量为1的边;
然后根据给出列表连这样两种边:食物—>牛,牛—>饮料,容量为1;
但这样无法确保每头牛只取一个食物和一个饮料,牛本身也是有容量的,所以要将牛拆点,容量为1;
在图上求解一次最大流,就是最后所求。
#include<cstdio> #include<iostream> #include<cstdlib> #include<algorithm> #include<ctime> #include<cctype> #include<cmath> #include<string> #include<cstring> #include<stack> #include<queue> #include<list> #include<vector> #include<map> #include<set> #define sqr(x) ((x)*(x)) #define LL long long #define itn int #define INF 0x3f3f3f3f #define PI 3.1415926535897932384626 #define eps 1e-10 #define maxm 4004 #define maxn 404 using namespace std; const int food=0; const int cow1=1; const int cow2=2; const int drink=3; inline int code(int id,int type) { return type*100+id; } int fir[maxn]; int u[maxm],v[maxm],cap[maxm],flow[maxm],nex[maxm]; int e_max; int iter[maxn],q[maxn],lv[maxn]; void add_edge(int _u,int _v,int _w) { int e; e=e_max++; u[e]=_u;v[e]=_v;cap[e]=_w; nex[e]=fir[u[e]];fir[u[e]]=e; e=e_max++; u[e]=_v;v[e]=_u;cap[e]=0; nex[e]=fir[u[e]];fir[u[e]]=e; } void dinic_bfs(int s) { int f,r; memset(lv,-1,sizeof lv); q[f=r=0]=s; lv[s]=0; while(f<=r) { int x=q[f++]; for (int e=fir[x];~e;e=nex[e]) { if (cap[e]>flow[e] && lv[v[e]]<0) { lv[v[e]]=lv[u[e]]+1; q[++r]=v[e]; } } } } int dinic_dfs(int _u,int t,int _f) { if (_u==t) return _f; for (int &e=iter[_u];~e;e=nex[e]) { if (cap[e]>flow[e] && lv[_u]<lv[v[e]]) { int _d=dinic_dfs(v[e],t,min(_f,cap[e]-flow[e])); if (_d>0) { flow[e]+=_d; flow[e^1]-=_d; return _d; } } } return 0; } int max_flow(int s,int t) { memset(flow,0,sizeof flow); int total_flow=0; for (;;) { dinic_bfs(s); if (lv[t]<0) return total_flow; memcpy(iter,fir,sizeof iter); int _f; while ((_f=dinic_dfs(s,t,INF))>0) total_flow+=_f; } return total_flow; } int main() { #ifndef ONLINE_JUDGE freopen("/home/fcbruce/文档/code/t","r",stdin); #endif // ONLINE_JUDGE int N,F,D,s,t,f,d,_u; scanf("%d%d%d",&N,&F,&D); e_max=0; memset(fir,-1,sizeof fir); s=0;t=(maxn)-1; for (int i=1;i<=F;i++) add_edge(s,code(i,food),1); for (int i=1;i<=D;i++) add_edge(code(i,drink),t,1); for (int i=1;i<=N;i++) { add_edge(code(i,cow1),code(i,cow2),1); scanf("%d%d",&f,&d); for (int j=0;j<f;j++) { scanf("%d",&_u); add_edge(code(_u,food),code(i,cow1),1); } for (int j=0;j<d;j++) { scanf("%d",&_u); add_edge(code(i,cow2),code(_u,drink),1); } } printf("%d\n",max_flow(s,t)); return 0; }