poj2226 发表于 2017-10-08 | 分类于 poj 一道很经典的题,因为一块儿泥地可以被横着的木板覆盖也可以被竖着的木板覆盖,所以对于每个联通块我们横纵坐标分别标号,然后连接对应的横纵标号建图,求一遍最小覆盖即可。 poj2226题目链接 贴出渣代码: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586#include<iostream>#include<cstring>#include<cstdio>using namespace std;char c[100][100];int f[100][100];int n,m;int fa[1000];bool vis[1000];int tot;int had[1000],nxt[160004],point[160004];inline void add(int x,int y){ tot++; point[tot]=y; nxt[tot]=had[x]; had[x]=tot;}bool cando(int x){ for(int i=had[x];i;i=nxt[i]) { int to=point[i]; if(!vis[to]) { vis[to]=1; if(fa[to]==0||cando(fa[to])) { fa[to]=x; return 1; } } } return 0;}int ns,ms;int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%s",c[i]+1); int ans=0; for(int i=1;i<=n;i++) { int t=0; for(int j=1;j<=m;j++) if(t==0&&c[i][j]=='*') { ns++; f[i][j]=ns; t=1; } else { if(t==1&&c[i][j]=='*') f[i][j]=ns; if(t==1&&c[i][j]=='.') t=0; } } for(int i=1;i<=m;i++) { int t=0; for(int j=1;j<=n;j++) if(t==0&&c[j][i]=='*') { ms++; add(f[j][i],ms); t=1; } else { if(t==1&&c[j][i]=='*') add(f[j][i],ms); if(t==1&&c[j][i]=='.') t=0; } } for(int i=1;i<=ns;i++) { memset(vis,0,sizeof(vis)); if(cando(i))ans++; } printf("%d\n",ans); return 0;}