您的位置:首页 > 其它

POJ2226 Muddy Fields——最小点覆盖问题——Pku2226

2011-09-01 17:36 375 查看
最小点覆盖问题,采用匈牙利算法。

证明一下算法的正确性:

定义一段无法向左右扩展的连续泥地为行连通块,一段无法向上下扩展的连续泥地为列连通块。我们把行连通块对应X集合,列连通块对应Y集合,如果一个行连通块与一个列连通块有交点且为空地,则对应在二分图中有一条边。显然木板的集合对应二分图的一个匹配,任意两个木板不可能共同存在于一个行/列连通块中,所以最少木板数目=最大匹配数。证毕。

Program POJ2226;//by_Poetshy
Const
maxn=50;
Var
i,j,k,m,n,sum,sum2,ans			:Longint;
map								:Array[1..maxn,1..maxn]of Char;
f								:Array[1..maxn,1..maxn,0..1]of Longint;
pre,other,last,res				:Array[1..maxn*maxn]of Longint;
state							:Array[1..maxn*maxn]of Boolean;

Function Dfs(i:Longint):Boolean;
var j,k:Longint;
begin
j:=last[i];
while j<>0 do
begin
k:=other[j];
if not state[k] then
begin
state[k]:=true;
if (res[k]=0)or(Dfs(res[k]))then
begin
res[k]:=i;
exit(true);
end;
end;
j:=pre[j];
end;
exit(false);
end;

BEGIN
readln(m,n);
for i:=1 to m do
begin
for j:=1 to n do
read(map[i,j]);
readln;
end;
fillchar(last,sizeof(last),0);
sum:=0;sum2:=0;ans:=0;
fillchar(f,sizeof(f),255);
for i:=1 to m do
for j:=1 to n do
if (map[i,j]='*') then
begin
if f[i,j,0]=-1 then
begin
inc(sum);k:=i;
while (k<=m)and(map[k,j]='*')do
begin
f[k,j,0]:=sum;
inc(k);
end;
end;
if f[i,j,1]=-1 then
begin
inc(sum2);k:=j;
while (k<=n)and(map[i,k]='*')do
begin
f[i,k,1]:=sum2;
inc(k);
end;
end;
end;//Prepare the graph
k:=0;
for i:=1 to m do
for j:=1 to n do
begin
if map[i,j]='*' then
begin
inc(k);
pre[k]:=last[f[i,j,0]];last[f[i,j,0]]:=k;other[k]:=f[i,j,1];
end;
end;
for i:=1 to sum do
begin
fillchar(state,sizeof(state),0);
if Dfs(i) then inc(ans);
end;
writeln(ans);
END.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: