二分图最小覆盖数

原来想随便找个最大流的题目练练手的,根据别人的列表在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.

posted on 2011-05-30 23:01  oa414  阅读(341)  评论(0编辑  收藏  举报

导航