二分图最小覆盖数

原来想随便找个最大流的题目练练手的,根据别人的列表在POJ上找了一道题,花了好长时间看懂了题目,然后想了一天,不想却碰到了新的知识,而且很多地方都有讲解。

题目:POJ1325

题解:左边是机器A的模式,右边是机器B的模式,用任务来连接这些模式,即某个任务可以用左边的模式a或者右边的模式b来做,那么就a连接b。我们的目的是找出最小的点集能保证任意的一个任务,都能有对应的模式。

算法:最小点覆盖数=二分图最大匹配数 匈牙利可秒之

体会:我傻X了,一个匈牙利总是在细节出错,而且变量没有每次初始化,在POJ上WA了好几次

参考资料:

《算法艺术与信息学竞赛》P331

《组合数学》(Richard A.Brualdi 机械工业出版社 原书第四版)P232

Matrix67 二分图最大匹配的König定理及其证明

ccy:König定理及其证明(最小覆盖点)

代码:

var

  a:array[0..1000,0..1000] of boolean;

  i,j,k,m,n,ans,p,x,y:longint;

  flag:array[0..1000] of boolean;

  link:array[0..1000] of longint;





function dfs(k:longint):boolean;

var

  i,j:longint;

begin

  for i:=1 to n+m do

    if a[k,i] and not flag[i] then

    begin

      flag[i]:=true;

      if (link[i]=0) or dfs(link[i]) then

      begin

        link[i]:=k;

        exit(true);

      end;

    end;

  exit(false);

end;





begin

  while not eof do

  begin

    read(n);

    if n=0 then break;

    readln(m,k);

    fillchar(link,sizeof(link),0);

    fillchar(a,sizeof(a),0);

    for i:=1 to k do

    begin

      readln(j,x,y);

      if (x<>0)and(y<>0) then

        a[x,n+y]:=true;

    end;

  ans:=0;

  for i:=1 to n+m do

  begin

    fillchar(flag,sizeof(flag),0);

    if dfs(i) then inc(ans);

  end;

  writeln(ans);

  end;

end.

你可能感兴趣的:(二分图)