【图论】【poj 3020】Antenna Placement
问题
给定你一个n*m的图,图中有些‘*’点,其他是‘0’点,在每个‘*’点可以建雷达,每个雷达可以覆盖其上下左右四个方向的‘*’点之一,问你最少建多少雷达,可以将这些‘*’点全部覆盖。
分析
二分图,构图,如果我们把每个‘*’点虚拟成一个节点,分布在二分图的两侧。然后,如果两点能相互覆盖,我们就在两点之间连一条边。要求的问题就转化成了,二分图最小边覆盖!
为什么是二分图呢,以为每个点只能覆盖出自身之外的一个节点,这恰好满足匹配的定义。
怎样求解二分图中的最小边覆盖呢。我们知道,一个匹配可以覆盖到2个不同的节点,那么二分图最大匹配覆盖到的节点数=最大匹配数*2。还没有被覆盖到的节点=总共的节点数-最大匹配数*2。所以,二分图最小边覆盖=最大匹配数+总共的节点数-最大匹配数*2=总的的节点数-最大匹配数
code
program liukeke; type pig=record x,y:longint; end; var a:array[1..1000,0..1000] of longint; pos:array[1..1000] of pig; match:array[1..1000] of longint; v:array[1..1000] of boolean; i,zu,ans,tot,n,m,j:longint; procedure init; var i,j:longint; ch:char; begin readln(n,m); for i:=1 to n do begin for j:=1 to m do begin read(ch); if ch='*' then begin inc(tot); pos[tot].x:=i; pos[tot].y:=j; end; end; readln; end; for i:=1 to tot do for j:=1 to tot do if i<>j then begin if ((abs(pos[i].x-pos[j].x)=1) and(abs(pos[i].y-pos[j].y)=0))or ((abs(pos[i].x-pos[j].x)=0) and(abs(pos[i].y-pos[j].y)=1))then begin inc(a[i,0]); a[i,a[i,0]]:=j; end; end; end; function dfs(s:longint):boolean; var i:longint; begin for i:=1 to a[s,0] do if not v[a[s,i]] 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 readln(zu); for i:=1 to zu do begin fillchar(a,sizeof(a),0); fillchar(pos,sizeof(pos),0); fillchar(match,sizeof(match),0); tot:=0; ans:=0; init; for j:=1 to tot do begin fillchar(v,sizeof(v),false); if dfs(j) then inc(ans); end; writeln(tot-ans>>1); end; end.