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

最小点覆盖问题,采用匈牙利算法。

证明一下算法的正确性:

定义一段无法向左右扩展的连续泥地为行连通块,一段无法向上下扩展的连续泥地为列连通块。我们把行连通块对应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.

你可能感兴趣的:(Field)