梦幻大PK
二分图最大匹配问题,用邻接矩阵就足够了,但我写的邻接表,那个back指针的用法很有趣,还有就是sap算法里面,回溯时,要栈顶的指针弹出来,刚开始调试怎么也没注意到这一点,后来看了一下以前写的代码,瞬间AC~
type
link=^node;
node=record x,c:longint; next,back:link; end;
var
vh,dis,pre,his:array[0..2002] of longint;
di,g,stack:array[0..2002] of link;
n,s,t:longint;
procedure connect(a,b,c:longint);
var
p1,p2:link;
begin
new(p1); new(p2);
p1^.x:=b; p1^.c:=c; p1^.back:=p2; p1^.next:=g[a]; g[a]:=p1;
p2^.x:=a; p2^.c:=0; p2^.back:=p1; p2^.next:=g[b]; g[b]:=p2;
end;
function sap:longint;
var
i,aug,top,min:longint;
j,j1:link;
flag:boolean;
begin
fillchar(dis,sizeof(dis),0);
fillchar(vh,sizeof(vh),0); vh[0]:=n;
di:=g; i:=s; aug:=maxlongint; top:=-1; sap:=0;
while dis[s]<n do begin
his[i]:=aug; flag:=false;
j:=di[i];while j<>nil do begin
if (j^.c>0)and(dis[j^.x]+1=dis[i]) then begin
flag:=true; di[i]:=j; if j^.c<aug then aug:=j^.c;
inc(top); stack[top]:=j;
pre[j^.x]:=i; i:=j^.x;
if i=t then begin
inc(sap,aug);
while top>=0 do begin
dec(stack[top]^.c,aug); inc(stack[top]^.back^.c,aug);
dec(top);
end;
i:=s;
aug:=maxlongint;
end;
break;
end;
j:=j^.next;
end;
if flag then continue;
min:=n-1;
j:=g[i];while j<>nil do begin
if (j^.c>0)and(dis[j^.x]<min) then begin
j1:=j; min:=dis[j^.x];
end;
j:=j^.next;
end;
di[i]:=j1;
dec(vh[dis[i]]); if vh[dis[i]]=0 then break;
dis[i]:=min+1; inc(vh[dis[i]]);
if i<>s then begin i:=pre[i]; aug:=his[i]; dec(top); end;
end;
end;
procedure main;
var
i,j,x:longint;
d:array[1..1000] of boolean;
begin
readln(n);
for i:=1 to n do begin
fillchar(d,sizeof(d),true);
read(j); while j>0 do begin read(x); d[x]:=false; dec(j); end; readln;
for j:=1 to n do if d[j] then connect(i,n+j,1);
end;
s:=2*n+1; t:=2*n+2;
for i:=1 to n do begin connect(s,i,1); connect(n+i,t,1); end;
n:=n*2+2;
write(sap);
end;
begin
main;
end.