考虑木板一定都尽量长,对于每一个污泥,最多只有两种木板会覆盖它(横着和竖的),将这两块木板连边,意味着每一条边两端端点中一定有一个点要被选,即最小点覆盖=最大匹配数。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 105 4 struct ji{ 5 int nex,to; 6 }edge[N*N]; 7 int E,n,m,t,ans,head[N*N],id[N][N],vis[N*N],flag[N*N]; 8 char s[N][N]; 9 void add(int x,int y){ 10 edge[E].nex=head[x]; 11 edge[E].to=y; 12 head[x]=E++; 13 } 14 bool dfs(int k){ 15 if (vis[k])return 0; 16 vis[k]=1; 17 for(int i=head[k];i!=-1;i=edge[i].nex){ 18 int v=edge[i].to; 19 if ((!flag[v])||(dfs(flag[v]))){ 20 flag[k]=v; 21 flag[v]=k; 22 return 1; 23 } 24 } 25 return 0; 26 } 27 int main(){ 28 scanf("%d%d",&n,&m); 29 for(int i=0;i<n;i++,t++){ 30 scanf("%s",s[i]); 31 for(int j=0;j<m;j++) 32 if (s[i][j]=='*')id[i][j]=t; 33 else t++; 34 } 35 memset(head,-1,sizeof(head)); 36 for(int j=0;j<m;j++,t++) 37 for(int i=0;i<n;i++) 38 if (s[i][j]=='*')add(t,id[i][j]); 39 else t++; 40 for(int i=0;i<n;i++) 41 for(int j=0;j<m;j++)t=max(t,id[i][j]); 42 for(int i=1;i<=t;i++){ 43 memset(vis,0,sizeof(vis)); 44 if (!flag[i])ans+=dfs(i); 45 } 46 printf("%d",ans); 47 }