POJ 3281 Dining 最大流 Dinic算法

Dining

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 10768   Accepted: 4938

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: NF, 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 cowi will eat, and the Di 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

题意:农夫为他的牛准备了F种食物和D种饮料。每头牛都有各自喜欢的食物和饮料,而每种食物和饮料只能分配给一头牛。最多有多少头牛可以同时得到喜欢的食物和饮料?

我的第一道网络流的题目。

开始的思路:建立一个源点s和一个汇点t,然后把食物饮料和s,t建图,食物在前,饮料在后,然后把牛看成是流,跑一遍dinic,看有多少头牛可以到达t

这样的思路是错的:因为牛从s出发的时候不同的牛可以选择的路是不同的。

要怎么样才可以消除这种关系呢?

即怎么样才可以使得所有路径对所有流都是平等的,只有容量的限制。

再整理一下:

每头牛可以走的路径不一样

如果把牛,食物,饮料都看成是点,则每个点只可以经过一次。

所以建图:s,食物,牛,牛,饮料,t,正向容量都是1

s—食物的边,饮料—t的边的容量都是1,就保证了每种食物,饮料只被流经过一次

而牛—牛的边的容量为1,就保证了牛只被流经过一次

建图后,直接dinic即可。

值得说的是,这道题今晚8:30做到9:30左右AC了。

然后9:30的时候删掉,重新再打一次,结果第二次打错了,找bug找到现在才过,历时2hours。

原因:这个图是有向边,然后在addedge(from,to)的时候,我把部分边的起点和终点写反了。

这个一定要注意,下次不能再犯。

  1 #include<cstring>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<queue>
  6
  7 using namespace std;
  8
  9 const int maxn=405;
 10 const int inf=0x3f3f3f3f;
 11
 12 struct Edge
 13 {
 14     int to,cap,rev;
 15 };
 16
 17 vector<Edge>edge[maxn];
 18 int level[maxn];
 19 int id[maxn];
 20 int s=0;
 21 int t;
 22
 23 void addedge(int from,int to)
 24 {
 25     edge[from].push_back((Edge){to,1,edge[to].size()});
 26     edge[to].push_back((Edge){from,0,edge[from].size()-1});
 27 }
 28
 29 void bfs()
 30 {
 31     memset(level,-1,sizeof(level));
 32
 33     queue<int>que;
 34     while(!que.empty())
 35         que.pop();
 36
 37     level[s]=0;
 38     que.push(s);
 39
 40     while(!que.empty())
 41     {
 42         int u=que.front();
 43         que.pop();
 44         for(int i=0;i<edge[u].size();i++)
 45         {
 46             Edge &e=edge[u][i];
 47             if(e.cap>0&&level[e.to]<0)
 48             {
 49                 level[e.to]=level[u]+1;
 50                 que.push(e.to);
 51             }
 52         }
 53     }
 54 }
 55
 56 int dfs(int u,int f)
 57 {
 58     if(u==t)
 59         return f;
 60     for(int &i=id[u];i<edge[u].size();i++)
 61     {
 62         Edge &e=edge[u][i];
 63         if(e.cap>0&&level[e.to]>level[u])
 64         {
 65             int d=dfs(e.to,min(e.cap,f));
 66             if(d>0)
 67             {
 68                 e.cap-=d;
 69                 edge[e.to][e.rev].cap+=d;
 70                 return d;
 71             }
 72         }
 73     }
 74     return 0;
 75 }
 76
 77 int solve()
 78 {
 79     int res=0;
 80     while(true)
 81     {
 82         bfs();
 83         if(level[t]<0)
 84             return res;
 85         memset(id,0,sizeof(id));
 86         int flow;
 87         while(flow=dfs(s,inf))
 88         {
 89             res+=flow;
 90         }
 91     }
 92 }
 93
 94 int main()
 95 {
 96     int N,F,D;
 97     while(~scanf("%d%d%d",&N,&F,&D))
 98     {
 99         for(int i=0;i<maxn;i++)
100             edge[i].clear();
101
102         t=F+2*N+D+1;
103         for(int i=1;i<=F;i++)
104             addedge(s,i);
105         for(int i=1;i<=D;i++)
106             addedge(F+2*N+i,t);
107         for(int i=1;i<=N;i++)
108             addedge(i+F,i+F+N);
109         for(int i=1;i<=N;i++)
110         {
111             int a,b;
112             scanf("%d%d",&a,&b);
113             for(int j=1;j<=a;j++)
114             {
115                 int u;
116                 scanf("%d",&u);
117                 addedge(u,i+F);
118             }
119             for(int j=1;j<=b;j++)
120             {
121                 int u;
122                 scanf("%d",&u);
123                 addedge(i+F+N,u+F+2*N);
124             }
125         }
126
127         printf("%d\n",solve());
128     }
129     return 0;
130 }

时间: 2024-10-05 16:01:22

POJ 3281 Dining 最大流 Dinic算法的相关文章

POJ 3281 Dining(最大流)

POJ 3281 Dining 题目链接 题意:n个牛,每个牛有一些喜欢的食物和饮料,每种食物饮料只有一个,问最大能匹配上多少只牛每个牛都能吃上喜欢的食物和喜欢的饮料 思路:最大流,建模源点到每个食物连一条边,容量为1,每个饮料向汇点连一条边容量为1,然后由于每个牛有容量1,所以把牛进行拆点,然后食物连向牛的入点,牛的出点连向食物,跑一下最大流即可 代码: #include <cstdio> #include <cstring> #include <queue> #in

POJ 3281 Dining (最大流)

Dining Time Limit: 2000MS   Memory Limit: 65536K       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

【网络流#7】POJ 3281 Dining 最大流 - 《挑战程序设计竞赛》例题

不使用二分图匹配,使用最大流即可,设源点S与汇点T,S->食物->牛->牛->饮料->T,每条边流量为1,因为流过牛的最大流量是1,所以将牛拆成两个点. 前向星,Dinic,复杂度:O(V2E) 直接套用模板 #include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set

poj 3281 Dining(最大流)

poj 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 prefer

POJ 3281 Dining(网络最大流)

http://poj.org/problem?id=3281 Dining Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9121   Accepted: 4199 Description Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she will consume no others.

POJ 3281 Dining(最大流建图 &amp;&amp; ISAP &amp;&amp; 拆点)

题目链接:http://poj.org/problem?id=3281 努力练建图ing!!! 题意:有 N 头牛,有 F 种食物和 D 种饮料,每种食物或饮料只能供一头牛享用,且每头牛只享用一种食物和一种饮料. 第2行-第N+1行.是牛i 喜欢A种食物,B种饮料,及食物种类列表和饮料种类列表. 问最多能使几头牛同时享用到自己喜欢的食物和饮料.->最大流. 本题难点是建图: 思路:一般都是左边一个集合表示源点与供应相连,右边一个集合表示需求与汇点相连. 但是本题,牛作为需求仍然是一个群体,但是供

网络最大流 dinic算法

一句话题意:给出一个网络图,以及其源点和汇点,求出其网络最大流 //dinic算法; //时间复杂度O(V^2E); #include<bits/stdc++.h> #define inf 999999 #define maxn 200000 using namespace std; int n,m,s,t; int ans=0; struct Edge { int to,next,w; }; struct Edge edge[maxn]; int head[maxn],val[maxn],p

POJ 3469.Dual Core CPU 最大流dinic算法模板

Dual Core CPU Time Limit: 15000MS   Memory Limit: 131072K Total Submissions: 24830   Accepted: 10756 Case Time Limit: 5000MS Description As more and more computers are equipped with dual core CPU, SetagLilb, the Chief Technology Officer of TinySoft C

HDU ACM 3572 Task Schedule 网络最大流-&gt;dinic算法

分析: 建图:每个任务和每一天分别看做一个点,添加源和汇点.源点和每个任务连一条边,每天边的容量为完成对应任务所需处理次数.若第i个任务能够在Si至Ei天处理,则由该任务向这些天分别连一条边,容量为1,表示此任务每天只能被处理一次.最后,每一天分别连一条边到汇点,容量为机器数M,即每天可以处理M个任务.若求出的最大流等于所有任务需要处理的次数之和,说明能完成任务:否则,不能. #include<iostream> #include<vector> #include<queue