SSL 1340 最小路径覆盖 最大匹配

先介绍一个较好的介绍包括最小路径覆盖等跟二分图最大匹配有关的问题的网站:http://blog.csdn.net/hellobabygogo3/article/details/7900812

题目:定义: 一个不含圈的有向图G中,G的一个路径覆盖是一个其结点不相交的路径集合P,图中的每一个结点仅包含于P中的某一条路径。路径可以从任意结点开始和结束,且长度也为任意值,包括0。请你求任意一个不含圈的有向图G的最小路径覆盖数。

因为最小路径覆盖数=G的定点数-最小路径覆盖中的边数(不要问我为什么),所以可以推出最小路径覆盖数=原图G的顶点数-二分图的最大匹配数。

于是乎我们就把点分成两边,每一边都是1到n,然后对于每一条边就在二分图中连一条有向边,再做最大匹配就好了。

下面附程序:

const
  maxn=120;

var
  t,l,n,m,i,x,y,ans:longint;
  a:array[1..maxn,1..maxn] of boolean;
  v:array[1..maxn] of boolean;
  link:array[1..maxn] of longint;

function find(x:longint):boolean;
var
  i,p:longint;
begin
  find:=false;
  for i:=1 to n do
    if (a[x,i])and(v[i]) then
    begin
      v[i]:=false;
      p:=link[i];
      link[i]:=x;
      if (p=0)or(find(p)) then exit(true);
      link[i]:=p;
    end;
end;

begin
  readln(t);
  for l:=1 to t do
  begin
    readln(n);
    readln(m);
    fillchar(a,sizeof(a),false);
    for i:=1 to m do
    begin
      readln(x,y);
      a[x,y]:=true;
    end;
    fillchar(link,sizeof(link),0);
    ans:=0;
    for i:=1 to n do
    begin
      fillchar(v,sizeof(v),true);
      if find(i) then inc(ans);
    end;
    writeln(n-ans);
  end;
end.

你可能感兴趣的:(SSL 1340 最小路径覆盖 最大匹配)