传送门:POJ3281
【题目大意】
有N头奶牛,每一头都有自己喜欢的食物和饮料,且它们只吃自己喜欢的东西。每头牛只能选一个食物与一个饮料现在有F种食物,D种饮料,求最多能够同时满足几头奶牛的需求。
【输入格式】
第一行N,F,D。N代表牛的数量;F代表食物的数量;D代表饮料的数量
接下来2..N+1行:每行前两个数:F[I]与D[I]代表这头牛喜欢食物与饮料的种类数,接下来F+D行代表他喜欢的食物与饮料。
【输出格式】
一个数X:代表最多几头牛能满足。
【大致思路】
Dinic求最大流+邻接表
【建图思路】
最直白的方式是将食物放在左边,分别与源点相连(容量:1);饮料放在右边,分别与汇点相连(容量:1);每头奶牛看作一个点,放在中间。每头奶牛都与其喜爱的食物和饮料连一条边(容量:MAX),然后求这个图的最大流就行了。
但是,题目有限制每头奶牛只能选一份餐,所以要在这个基础上做限制:将表示牛的点一分为二(牛1和牛2),牛1决定所选的食物(与喜爱食物连边),牛2决定所选饮料(与喜爱饮料连边),两者之间再连一条容量为1的边即可。这个做法让每个牛只能选一种套餐。
【代码】
type
dinic=record
y,r,next,op:longint;
end;
var
g:array[-1..20000] of dinic;
level,q,h:array[-1..410] of longint;
n,m,i,ans,a,b,c,j,num,vs,vt,f,d,ff,dd,x:longint;
function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
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<>0 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;
function bfs:boolean;
var
i,f,r,tmp,v,u,j:longint;
begin
fillchar(level,sizeof(level),0);
f:=1; r:=1;
q[1]:=vs;
level[vs]:=1;
repeat
v:=q[f];
tmp:=h[v];
while tmp<>0 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;
procedure add(a,b,c:longint);
begin
inc(num);
g[num].y:=b;
g[num].r:=c;
g[num].op:=num+1;
g[num].next:=h[a];
h[a]:=num;
inc(num);
g[num].y:=a;
g[num].r:=0;
g[num].op:=num-1;
g[num].next:=h[b];
h[b]:=num;
end;
procedure init;
begin
fillchar(h,sizeof(h),0);
num:=0;
ans:=0;
readln(n,f,d);
vs:=0;
vt:=401;
for i:=1 to f do add(vs,i+200,1);
for i:=1 to d do add(i+300,vt,1);
for i:=1 to n do
begin
add(i,i+100,1);
read(ff,dd);
for j:=1 to ff do
begin
read(x);
add(x+200,i,maxlongint);
end;
for j:=1 to dd do
begin
read(x);
add(i+100,x+300,maxlongint);
end;
readln;
end;
end;
procedure main;
begin
init;
while bfs do
begin
ans:=ans+dfs(vs,maxlongint);
end;
writeln(ans);
end;
begin
main;
end.