二分图匹配----匈牙利算法之六

poj 2226 Muddy Fields

/*

题意 :有R×C方阵,'*'表示洼地,需要铺上宽度为1的木板,长度不限,只能横放或竖放.木板可以重叠,但不能覆盖'.'

求覆盖所有'*'洼地所用的最少木板数.

构图: 将所有横向且连续(一个或以上)的'*'看成一个点并对其进行编号,所有的编号都为集合X内的编号。同样地,将所有的竖向且连续(一个或以上)的'*'看成一个点并对其编号,所有的编号都为集合Y内的编号

对于原图里的'*',设其在横向X编号为i,在竖向Y编号为j,则在点 Xi 和点 Yj 间连一条边,

这样构成一个二分图,问题就变成一个最小点覆盖问题,于是转化成二分图的最大匹配

*/

poj 2226 Muddy Fields
#include<iostream>            //求二分图的最小覆盖点集
#include<cstring>
using namespace std;
char ch[60][60];
int r,c,row[60][60],colo[60][60];
int edge[3000][3000],vis[3000],result[3000],x,y;
bool find(int a)
{
for(int i=1;i<=y;++i)
if(edge[a][i]==1&&vis[i]==0)
{
vis[i]
=1;
if(result[i]==0||find(result[i]))
{
result[i]
=a;
return true;
}
}
return false;
}
int main()
{
cin
>>r>>c;
memset(edge,
0,sizeof(edge));
memset(result,
0,sizeof(result));
for(int i=1;i<=r;++i)
{
cin
>>ch[i]+1;
}
int s,t;
x
=0;
for(int i=1;i<=r;++i) //在水平方向上查找连续的'*'
{
s
=1;
do
{
while(s<=c&&ch[i][s]=='.')
s
++;
t
=s;
while(t+1<=c&&ch[i][t+1]=='*')
t
++;
if(t<=c)
{
++x;
for(int j=s;j<=t;++j)
row[i][j]
=x;
s
=t+1;
}
}
while(t<=c);
}
y
=0;
for(int j=1;j<=c;++j) //在垂直方向上查找连续的'*'
{
s
=1;
do
{
while(s<=r&&ch[s][j]=='.')
s
++;
t
=s;
while(t+1<=r&&ch[t+1][j]=='*')
t
++;
if(t<=r)
{
++y;
for(int i=s;i<=t;++i)
colo[i][j]
=y;
s
=t+1;
}
}
while(t<=r);
}
for(int i=1;i<=r;++i)
for(int j=1;j<=c;++j)
{
if(ch[i][j]=='*')
edge[row[i][j]][colo[i][j]]
=1; //如果是'*'则在相应的集合X,Y编号内连一条边
}
int ans=0;
for(int i=1;i<=x;++i)
{
memset(vis,
0,sizeof(vis));
if(find(i))
{
ans
++;
}
}
cout
<<ans<<endl;
return 0;
}

  

posted on 2011-07-19 21:39  sysu_mjc  阅读(162)  评论(0编辑  收藏  举报

导航