【图论】【poj 3041】Asteroids

问题

给你一个n*n的图,上面有m个需要清楚的障碍,每次可以消除一行或者一列上的障碍物。问你最少用多少次,可以消除图上的所有障碍。

分析

关键是构图,我们将原图抽象成一个二分图:左边是x,右边是y,如果(x,y)上有障碍物,那么就连一条边。我们的任务是消除障碍物,也就是说,用最少的点覆盖图中所有的边!

也就是求二分图的最小点集覆盖!

我们用到一个强大的定理:二分图最小点集覆盖数=最大匹配数,网上有好多证明。

这里大体说一种思路,如果最大匹配的边涉及到的点无法将所有边覆盖,那么当前匹配一定不是最大匹配!

code

program liukee;
var
  a:array[1..1200,0..1200] of longint;
  match:array[1..1200] of longint;
  v:array[1..1200] of boolean;
  n,i,k,ans:longint;
procedure init;
var
  x,y:longint;
begin
  readln(n,k);
  for i:=1 to k do
  begin
    readln(x,y);
	inc(a[x,0]);
	inc(a[y+n,0]);
	a[x,a[x,0]]:=y+n;
	a[y+n,a[y+n,0]]:=x;
  end;
end;

function dfs(s:longint):boolean;
var
  i:longint;
begin
  for i:=1 to a[s,0] do
    if v[a[s,i]]=false then
    begin
	  v[a[s,i]]:=true;
	  if (match[a[s,i]]=0)or(dfs(match[a[s,i]])) then
	  begin
	    match[a[s,i]]:=s;
		exit(true);
	  end;
    end;
  exit(false);
end;

begin
  init;
  for i:=1 to n+n do
  begin
    fillchar(v,sizeof(v),0);
    if dfs(i) then inc(ans);
  end;
  writeln(ans>>1);
end.

反思

要想到二分图,抽象。掌握定理!

posted @ 2011-03-20 20:46  liukee  阅读(233)  评论(0编辑  收藏  举报