[二分图]JZOJ 4612 游戏
分析
非常眼熟,行列唯一匹配,可以想到二分图
只是多了大石头的干扰,那么我们把所有的行联通和列联通求出连边即可
注意软石头不能连接它所在的行列,但是可以让行联通或列联通
#include <iostream> #include <cstdio> #include <cstring> #include <memory.h> using namespace std; const int N=60; struct Graph { int v,nx; }g[2*N*N*N]; int cnt,list[N*N]; int n,m; char c[N][N]; int h[N][N],l[N][N],hcnt,ans; int connect[N*N]; bool b,vis[N*N]; void Add(int u,int v) { g[++cnt]=(Graph){v,list[u]};list[u]=cnt; } bool DFS(int u) { if (vis[u]) return 0;vis[u]=1; for (int i=list[u];i;i=g[i].nx) if (!connect[g[i].v]||DFS(connect[g[i].v])) { connect[g[i].v]=u; return 1; } return 0; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%s",c[i]+1); for (int i=1;i<=n;i++) { if (!b) cnt++; for (int j=1;j<=m;j++) if (c[i][j]=='*') h[i][j]=cnt,b=0; else if (!b&&c[i][j]=='#') cnt++,b=1; } b=0; for (int i=1;i<=m;i++) { if (!b) cnt++; for (int j=1;j<=n;j++) if (c[j][i]=='*') l[j][i]=cnt,b=0; else if (!b&&c[j][i]=='#') cnt++,b=1; } hcnt=cnt;cnt=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (h[i][j]&&l[i][j]) Add(h[i][j],l[i][j]); for (int i=1;i<=hcnt;i++) { memset(vis,0,sizeof vis); if (DFS(i)) ans++; } printf("%d",ans); }
在日渐沉没的世界里,我发现了你。