【图论】【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.
反思
要想到二分图,抽象。掌握定理!