poj3281

Dining

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 10843   Accepted: 4974

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 cow i 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.

题目大意:有F种食物,D种饮料,N头奶牛,只能吃某种食物和饮料(而且只能吃特定的一份),一种食物被一头牛吃了之后,其余牛就不能吃了

第一行有N,F,D三个整数

接着2-N+1行代表第i头牛,前面两个整数是Fi与Di(食物与饮料的种类数量),接着是食物的种类与饮料的种类

要求输出最多分配能够满足的牛的数量

解题思路:建图,有2*n+f+d+2个顶点

0表示源点,2*n+f+d+1表示汇点

由源点指向食物,再由食物指向牛,牛再指向对应的饮料,饮料再指向汇点

当然要使每一头牛都对应每一份食物与饮料,所以应该牛i指向牛i再指向饮料,这样就可以避免一头牛只占用多份食物与饮料了

全部是有向的边,而且权值全部为1

我在这里是1到f为食物点,f+1到f+2*n为牛点,f+2*n+1到f+2*n+d为饮料点

代码:

type

edge=record

y,r,next,op:longint;

end;

var

g:array[0..10000] of edge;

level,q,h:array[0..10000] of longint;

n,m,f,i,j,a,b,c,tot,vs,ii,vt,x,y,k,ans:longint;

s:string;

function bfs:boolean;

var

i,f,r,tmp,v,u:longint;

begin

fillchar(level,sizeof(level),0);

f:=1;  r:=1;

q[f]:=vs;  level[vs]:=1;

repeat

v:=q[f];    tmp:=h[v];

while tmp<>-1 do

begin

u:=g[tmp].y;

if (g[tmp].r<>0) and (level[u]=0) then

begin

level[u]:=level[v]+1;

inc(r);    q[r]:=u;

if u=vt then exit(true);

end;

tmp:=g[tmp].next;

end;

inc(f);

until f>r;

exit(false);

end;

function min(x,y:longint):longint;

begin

if x<y then

exit(x);

exit(y);

end;

function dfs(v,a:longint):longint;

var

ans,flow,tmp,u,value:longint;

begin

if (v=vt) or (a=0) then exit(a);

ans:=0;  tmp:=h[v];

while tmp<>-1 do

begin

u:=g[tmp].y;    value:=g[tmp].r;

if (level[u]=level[v]+1)  then

begin

flow:=dfs(u,min(a,value));

if flow<>0 then

begin

g[tmp].r:=g[tmp].r-flow;

g[g[tmp].op].r:=g[g[tmp].op].r+flow;

ans:=ans+flow;

a:=a-flow;

if a=0 then break;

end;

end;

tmp:=g[tmp].next;

end;

exit(ans);

end;

procedure add(a,b,c:longint);

begin

inc(tot);

g[tot].y:=b;

g[tot].r:=c;

g[tot].next:=h[a];

h[a]:=tot;

g[tot].op:=tot+1;

inc(tot);

g[tot].y:=a;

g[tot].r:=0;

g[tot].next:=h[b];

h[b]:=tot;

g[tot].op:=tot-1;

end;

begin

while not eof do

begin

fillchar(g,sizeof(g),0);

fillchar(h,sizeof(h),$ff);

fillchar(level,sizeof(level),0);

fillchar(q,sizeof(q),0);

readln(n,f,m);

tot:=0;

ans:=0;

vs:=0;

vt:=2*n+f+m+1;

for i:=1 to n do

begin

x:=0;

y:=0;

a:=0;

add(i+f,i+n+f,1);

readln(s);

for j:=1 to length(s) do

begin

if s[j]=‘ ‘ then

break;

x:=x*10+ord(s[j])-ord(‘0‘);

end;

ii:=j+1;

for j:=ii to length(s) do

begin

if s[j]=‘ ‘ then

break;

y:=y*10+ord(s[j])-ord(‘0‘);

end;

k:=0;

ii:=j+1;

while k<x do

begin

if (s[ii]=‘ ‘) or (ii>length(s)) then

begin

add(a,f+i,1);

a:=0;

inc(ii);

inc(k);

end else

begin

a:=a*10+ord(s[ii])-ord(‘0‘);

inc(ii);

end;

end;

k:=0;

while k<y do

begin

if (s[ii]=‘ ‘) or (ii>length(s)) then

begin

add(f+n+i,f+2*n+a,1);

a:=0;

inc(ii);

inc(k);

end else

begin

a:=a*10+ord(s[ii])-ord(‘0‘);

inc(ii);

end;

end;

end;

for i:=1 to f do

add(0,i,1);

for i:=1 to m do

add(i+2*n+f,2*n+f+m+1,1);

while bfs do

begin

ans:=ans+dfs(vs,maxlongint);

end;

writeln(ans);

end;

end.

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2025-01-31 23:39:47

poj3281的相关文章

poj3281 Dining

---恢复内容开始--- Dining Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9587   Accepted: 4426 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 c

解题报告 之 POJ3281 Dining

解题报告 之 POJ3281 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

POJ-3281 Dining 最大流 拆点

题目链接:https://cn.vjudge.net/problem/POJ-3281 题意 题意找kuangbin的用了. 有N头牛,F个食物,D个饮料. N头牛每头牛有一定的喜好,只喜欢几个食物和饮料. 每个食物和饮料只能给一头牛.一头牛只能得到一个食物和饮料. 而且一头牛必须同时获得一个食物和一个饮料才能满足.问至多有多少头牛可以获得满足. 思路 建图如下就完事了: 提交过程 AC 代码 #include <queue> #include <cstdio> #include

[POJ3281]Dining 最大流(建图奇葩)

题目链接:http://poj.org/problem?id=3281 参考了某犇做的PPT.对于此题的解释有如下内容(我只是搬运工). [题目大意] 有F种食物和D种饮料,每种食物或饮料只能供一头牛享用,且每头牛只享用一种食物和一种饮料.现在有N头牛,每头牛都有自己喜欢的食物种类列表和饮料种类列表,问最多能使几头牛同时享用到自己喜欢的食物和饮料.(1 <= F <= 100, 1 <= D <= 100, 1 <= N <= 100) 此题的建模方法比较有开创性.以往

poj3281 Dining 最大流(奇妙的构图)

我是按照图论500题的文档来刷题的,看了这题怎么也不觉得这是最大流的题目.这应该是题目做得太少的缘故. 什么是最大流问题?最大流有什么特点? 最大流的特点我觉得有一下几点: 1.只有一个起点.一个终点.如果不是,我们可以构造超级源点,超级汇点. 2.边的容量有上限(有上下限的是另外一种特殊的最大流). 3.最后求的是一个最大值. 这题可以找到一些影子,一头奶牛只能吃一种食物,喝一种饮料.如果只有一种限制我们能很快反应过来(二分最大匹配),但是两种限制就增加了难度.不过还是可以理解为对边的权值的限

poj3281 dining 经典最大流建模方法

题意:有f中食物和D种饮料,每头牛只能享用一种食物和饮料,每个食物跟饮料也只能被一头牛享用.现在有n头牛,每头牛都有自己喜欢的食物种类列表和饮料列表,问最多能使几头牛同时享用到自己喜欢的食物和饮料.f,d,n都是一百以内的. 思路:就不说一开始的想法了,是最近学习的最大流的建模里面的新的方法. 之前做过几道题,比如poj2391这道,它是比较一般的左边一些点代表着供应,2391这道题就是每个点的牛的数量,右边一个点集代表了需求并与汇点连接,这道题就是每个点能容纳的牛数,然后拆点联一下套模板就好了

poj3281(最大流)

传送门:Dining 题意:一些牛,一些食物,一些饮料,每头牛都有其喜欢的几种食物和几种饮料,求最多能给多少头牛即找到食物又找到饮料~也就是有多少个 牛---食物---饮料 的匹配,而且满足一一匹配,每个牛,食物,或饮料都只能使用一次. 分析:如果直接源点-食物-牛-汇点这样建图,那么可能会很多份食物通过某头牛传送过去,不能保证每头牛吃一份食物,因此拆点,把每头牛拆成牛-牛,边权为1,这样就能保证每头牛只能吃一份了. #pragma comment(linker,"/STACK:10240000

【POJ3281】Dining 网络流

题意:n牛m食品p饮品 第牛有ai种可行食品,bi种可行饮品 现在进行搭配,一头牛如果既有一份可行食品又有一份可行饮品就称为被满足. 求最多满足. 题解: 别忘了牛拆点. 代码: #include <cmath> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 405 //

poj3281网络流之最大流

加一个源点和汇点,把每头牛拆成两个点,不拆点的话可能会出现多对食物与饮料被一个牛享用的情况,拆点后流量为1,不能同时通过了 然后用最大流处理,每个链接边都是1 #include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<vector> #include<cstdio> #include<cassert>