二分图匹配题,这个题是求用最少的木板把所有的低洼处填上。这个题构图个人觉得非常巧妙,首先对于每个低洼处,它不是横着木板覆盖就是竖着木板覆盖,那么这样的话我们可以把低洼横着和竖着进行编号(能用一个木板连接的编相同的号),然后对于每个低洼处横着和竖着的编号进行连边,然后就变成了求最少的点去覆盖这些所有的边~
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;
const int maxn=55;
const int maxm=maxn*maxn;
int n,m,cnt,id[maxn][maxn],link[maxm];
char map[maxn][maxn];
vector<int> g[maxm];
bool vis[maxm];
void Init()
{
memset(id,0,sizeof(id));
memset(link,-1,sizeof(link));
for(int i=0;i<=n*m;i++)
g[i].clear();
}
bool find(int u)
{
for(int i=0;i<g[u].size();i++)
if(!vis[g[u][i]])
{
vis[g[u][i]]=1;
if(link[g[u][i]]==-1||find(link[g[u][i]]))
{
link[g[u][i]]=u;
return true;
}
}
return false;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
Init();
for(int i=1;i<=n;i++)
scanf("%s",map[i]+1);
cnt=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
while(j<=m&&map[i][j]=='.')
j++;
if(j<=m&&map[i][j]=='*')
{
cnt++;
while(j<=m&&map[i][j]=='*')
{
id[i][j]=cnt;
j++;
}
}
}
cnt=0;
for(int j=1;j<=m;j++)
for(int i=1;i<=n;i++)
{
while(i<=n&&map[i][j]=='.')
i++;
if(i<=n&&map[i][j]=='*')
{
cnt++;
while(i<=n&&map[i][j]=='*')
{
g[cnt].push_back(id[i][j]);
i++;
}
}
}
int ans=0;
for(int i=1;i<=cnt;i++)
{
memset(vis,0,sizeof(vis));
if(find(i))
ans++;
}
printf("%d\n",ans);
}
return 0;
}