二分图匹配题,这个题是求用最少的木板把所有的低洼处填上。这个题构图个人觉得非常巧妙,首先对于每个低洼处,它不是横着木板覆盖就是竖着木板覆盖,那么这样的话我们可以把低洼横着和竖着进行编号(能用一个木板连接的编相同的号),然后对于每个低洼处横着和竖着的编号进行连边,然后就变成了求最少的点去覆盖这些所有的边~
代码:
#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; }