[Rqnoj-192]梦幻大PK

来源:互联网 发布:深圳龙华行知小学网站 编辑:程序博客网 时间:2024/05/04 08:34

梦幻大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.