标签:二分匹配
//给r*c的 field ,有的地方有水,用宽度为1,长度任意的木板将这些有水的地方,
//遮住,木板可以相互叠加,木板不能遮住有草的地方
//可以每行中的连续的格子看成一个点xi,每一列中连续的格子看成一个点yj
//将每一个有水的格子看成一条边连接对应的xi , yj
//那么其最小点覆盖即为答案
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std ;
const int maxn = 2110 ;
int map[maxn][maxn] ;
int id[maxn][maxn] ;
char str[maxn][maxn] ;
int match[maxn] ;
int vis[maxn] ;
int n , len_1 , len_2 , m;
bool find(int st)
{
for(int i = 1;i <= len_2;i++)
if(!vis[i] && map[st][i])
{
vis[i] = 1 ;
if(match[i] == -1 || find(match[i]))
{
match[i] = st;
return true ;
}
}
return false ;
}
int main()
{
//freopen("in.txt" ,"r" ,stdin) ;
while(~scanf("%d %d" , &n , &m))
{
memset(map , 0 , sizeof(map)) ;
memset(match , -1 , sizeof(match)) ;
len_1 = 1 ;len_2 = 1;
for(int i = 1;i <= n;i++)
{
scanf("%s" , &str[i][1]) ;
for(int j = 1;j <= m;j++)
{
if(str[i][j] == ‘*‘)
id[i][j] = len_1;
if(str[i][j] == ‘.‘ && str[i][j-1] == ‘*‘)
len_1++;
}
if(str[i][m] != ‘.‘)len_1++;
}
for(int j = 1;j <= m;j++)
{
for(int i = 1;i <= n;i++)
{
if(str[i][j] == ‘*‘)
map[id[i][j]][len_2] = 1 ;
if(str[i][j] == ‘.‘ && str[i-1][j] == ‘*‘)
len_2++ ;
}
if(str[n][j] != ‘.‘)
len_2++;
}
int ans = 0 ;
for(int i = 1;i <= len_1 ;i++)
{
memset(vis ,0 , sizeof(vis)) ;
if(find(i))
ans++ ;
}
cout<<ans<<endl;
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
poj2226Muddy Fields 二分匹配之最小点覆盖
标签:二分匹配
原文地址:http://blog.csdn.net/cq_pf/article/details/47300461