BZOJ 4554

来源:互联网 发布:如何评价慈禧太后知乎 编辑:程序博客网 时间:2024/06/06 08:52

   这道题是一道经典的二分图匹配问题,我们可以把每一横行,每一纵列的连通块求出来,对于每一个不是硬石头的位置,我们把它所属于的横连通块和纵连通块连一条边,最后求一遍最大匹配,表示横连通块与纵连通块间2选1。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define maxn 100005int flag[maxn],link[maxn],l;int pre[maxn],other[maxn],last[maxn],totx,toty;int numx[55][55],numy[55][55],n,m,ans,vis_time;char s[55][55];void connect(int x,int y){l++;pre[l]=last[x];last[x]=l;other[l]=y;}bool find_p(int u){for (int p=last[u];p;p=pre[p]) {int v=other[p];if (flag[v]!=vis_time) {flag[v]=vis_time;if (link[v]==0||find_p(link[v])) {link[v]=u;return 1;}}}return 0;}int main(){scanf("%d%d",&n,&m);for (int i=1;i<=n;i++) scanf("%s",s[i]+1);for (int i=1;i<=n;i++) {int t=1;while (t<=m) {while (s[i][t]=='#') t++;totx++;while (s[i][t]=='*'||s[i][t]=='x') {numx[i][t]=totx; t++;}}}for (int j=1;j<=m;j++) {int t=1;while (t<=n) {while (s[t][j]=='#') t++;toty++;while (s[t][j]=='*'||s[t][j]=='x') {numy[t][j]=toty;t++;}}}for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (s[i][j]=='*') connect(numx[i][j],numy[i][j]);for (int i=1;i<=totx;i++) {vis_time++;if (find_p(i)) ans++;}printf("%d\n",ans);return 0;}


0 0
原创粉丝点击