UOJ 一般图的最大匹配(带花树算法模板)

裸模板,UOJ上有模板题,可以刷一刷
program bzoj;
var
   ans,x,y,t,w,i,n,m,tot:longint;
   g:array[0..1000,0..1000]of boolean;
   next1,mark,line,vis,match,head,a,next,belong:array[0..100000]of longint;
procedure add(x,y:longint);
begin
     inc(tot);
     next1[tot]:=head[x];
     head[x]:=tot;
     a[tot]:=y;

     inc(tot);
     next1[tot]:=head[y];
     head[y]:=tot;
     a[tot]:=x;
end;
function findb(x:longint):longint;
begin
     if belong[x]=x
     then exit(x)
     else
         begin
              belong[x]:=findb(belong[x]);
              exit(belong[x]);
         end;
end;
function lca(x,y:longint):longint;
var
   t,temp:longint;
begin
     t:=1;
     while true do
     begin
          if x<>-1
          then
              begin
                   x:=findb(x);
                   if vis[x]=1
                   then exit(x);
                   vis[x]:=1;
                   if match[x]<>-1
                   then x:=next[match[x]]
                   else x:=-1;
              end;
          temp:=x;
          x:=y;
          y:=temp;
     end;
end;

procedure unit1(x,y:longint);
begin
     if (findb(x)<>findb(y))
     then belong[findb(x)]:=findb(y);
end;
procedure group(x,p:longint);
var
   a1,a2:longint;
begin
     while x<>p do
     begin
          a1:=match[x];
          a2:=next[a1];
          if findb(a2)<>p
          then next[a2]:=a1;
          if mark[a1]=2
          then
              begin
                   inc(w);
                   line[w]:=a1;
                   mark[a1]:=1;
              end;
          if mark[a2]=2
          then
              begin
                   inc(w);
                   line[w]:=a2;
                   mark[a2]:=2;
              end;
          unit1(x,a1);
          unit1(a1,a2);
          x:=a2;
     end;
end;
procedure aug(s:longint);
var
   i,x,m,temp,u,v,mv:longint;
begin
     for i:=0 to n do
     begin
          next[i]:=-1;
          belong[i]:=i;
          mark[i]:=0;
          vis[i]:=0;
     end;
     mark[s]:=1;
     t:=1;
     w:=1;
     line[w]:=s;
     while (t<=w)and(match[s]=-1) do
     begin
          x:=line[t];
          m:=head[x];
          while m<>-1 do
          begin
               if (match[x]<>a[m])and(findb(x)<>findb(a[m]))and(mark[a[m]]<>2)
               then
                   begin
                        if mark[a[m]]=1
                        then
                            begin
                                 temp:=lca(x,a[m]);
                                 if findb(x)<>temp
                                 then next[x]:=a[m];
                                 if findb(a[m])<>temp
                                 then next[a[m]]:=temp;
                                 group(x,temp);
                                 group(a[m],temp);
                            end
                        else
                            begin
                                 if match[a[m]]=-1
                                 then
                                     begin
                                          next[a[m]]:=x;
                                          u:=a[m];
                                          while u<>-1 do
                                          begin
                                               v:=next[u];
                                               mv:=match[v];
                                               match[v]:=u;
                                               match[u]:=v;
                                               u:=mv;
                                          end;
                                          break;
                                     end
                                 else
                                     begin
                                          next[a[m]]:=x;
                                          inc(w);
                                          line[w]:=match[a[m]];
                                          mark[line[w]]:=1;
                                          mark[a[m]]:=2;
                                     end;
                            end;
                   end;
               m:=next1[m];
          end;
     end;
end;
begin
     assign(input,'bzoj.in');
     assign(output,'bzoj.out');
     reset(input);
     rewrite(output);
     read(n,m);
     fillchar(g,sizeof(g),false);
     for i:=0 to n do
     head[i]:=-1;
     for i:=1 to m do
     begin
          read(x,y);
          dec(x);
          dec(y);
          if (x<>y)and(not g[x,y])
          then
              begin
                   add(x,y);
                   g[x,y]:=true;
                   g[y,x]:=true;
              end;
     end;
     dec(n);
     for i:=0 to n do
     begin
          match[i]:=-1;
     end;
     for i:=0 to n do
     begin
          if match[i]=-1
          then aug(i);
     end;
     for i:=0 to n do
     begin
          if match[i]<>-1
          then inc(ans);
     end;
     writeln(ans);
     close(input);
     close(output);
end.   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值