[BZOJ1143] CTSC2008 祭祀river floyed+二分图匹配

本文介绍如何使用Floyd算法判断两点间连通性,并通过二分图的最大匹配解决最小点覆盖问题。首先利用Floyd算法进行点间连通性的预处理,接着将问题转化为求解最大匹配,最后通过计算得到最小点覆盖的解。

先用floyed判断两点是否联通。
把一个点v拆成vx,vy。如果i能到达j,那么连边(ix,jy)。
求最大点独立集,即最大匹配。
剩下的点都两两不联通了,于是答案就等于总点数-最大匹配。
二分图相关结论:
最小点覆盖(用最少的点覆盖所有的边)=最大匹配
最小边覆盖(用最少的边覆盖所有的点)=最大匹配+总点数-2*最大匹配=总点数-最大匹配
因为除了匹配边覆盖的点,剩下的点每个需要一条边覆盖。
最大点独立集(最大的两两不联通的点集)=总点数-最小点覆盖=总点数-最大匹配
因为删掉那些在最小点覆盖里的点以后,就已经删掉所有边了

代码

type
  edge=^edgenode;
  edgenode=record
    t:longint;
    next:edge;
  end;
var
  n,m,u,v,i,j,k,ans:longint;
  con:array[1..210]of edge;
  link:array[1..210]of longint;
  f:array[1..110,1..110]of boolean;
  visit:array[1..210]of boolean;
procedure ins(x,y:longint);
var
  p:edge;
begin
  new(P);
  p^.t:=y;
  p^.next:=con[x];
  con[x]:=p;
end;
function pipei(x:longint):boolean;
var
  p:edge;
begin
  pipei:=false;
  p:=con[x];
  visit[x]:=true;
  while p<>nil do
  begin
    if visit[p^.t]=false then
    begin
      visit[p^.t]:=true;
      if (link[p^.t]=-1)or(pipei(link[p^.t])=true) then
      begin
        link[p^.t]:=x;
        exit(true);
      end;
    end;
    p:=p^.next;
  end;
end;
begin
  readln(n,m);
  for i:=1 to m do
  begin
    readln(u,v);
    f[u,v]:=true;
  end;
  for k:=1 to n do
    for i:=1 to n do
      for j:=1 to n do
        f[i,j]:=f[i,j]or(f[i,k] and f[k,j]);
  for i:=1 to n do
    for j:=1 to n do
      if f[i,j]=true then begin  ins(i,j+n);  end;
  for i:=1 to n do
    link[i+n]:=-1;
  for i:=1 to n do
  begin
    fillchar(visit,sizeof(visit),false);
    if pipei(i)=true then inc(ans);
  end;
  writeln(n-ans);


end.   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值