【图论】【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.
浙公网安备 33010602011771号