n<=50 * m<=50的地图,每块地‘*’表示一定要被填上,‘.’表示一定不能填上,用1*l或l*1,l自定,的板填起来,求最少几块板。
如果是做过那种“一炮打一列或一行,求几炮把地图上的点打掉”的二分图经典题,那就可以类比了。不过这里的行和列是基于联通块的,所以预处理出行联通块和列联通块并编号,一个点选,意味着它对应的行联通块和列联通块至少选一个,因此连边。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<algorithm> 5 //#include<iostream> 6 using namespace std; 7 8 int n,m; 9 bool mp[55][55]; 10 char s[55];int belx[55][55],bely[55][55],cntx=0,cnty=0; 11 #define maxn 5011 12 #define maxm 5011*4 13 const int inf=0x3f3f3f3f; 14 struct Network 15 { 16 struct Edge{int to,next,cap,flow;}edge[maxm];int first[maxn],le; 17 Network() {le=2;memset(first,0,sizeof(first));} 18 int n,s,t; 19 void in(int x,int y,int cap) {Edge &e=edge[le];e.to=y;e.cap=cap;e.flow=0;e.next=first[x];first[x]=le++;} 20 void insert(int x,int y,int cap) {in(x,y,cap);in(y,x,0);} 21 int que[maxn],head,tail;int dis[maxn],cur[maxn]; 22 bool bfs() 23 { 24 que[head=(tail=1)-1]=s; 25 memset(dis,0,sizeof(dis));dis[s]=1; 26 while (head!=tail) 27 { 28 const int now=que[head++]; 29 for (int i=first[now];i;i=edge[i].next) 30 { 31 const Edge &e=edge[i]; 32 if (e.cap>e.flow && !dis[e.to]) 33 { 34 dis[e.to]=dis[now]+1; 35 que[tail++]=e.to; 36 } 37 } 38 } 39 return dis[t]; 40 } 41 int dfs(int x,int a) 42 { 43 if (x==t || !a) return a; 44 int flow=0,f; 45 for (int &i=cur[x];i;i=edge[i].next) 46 { 47 Edge &e=edge[i]; 48 if (dis[e.to]==dis[x]+1 && (f=dfs(e.to,min(a,e.cap-e.flow)))>0) 49 { 50 flow+=f; 51 e.flow+=f; 52 edge[i^1].flow-=f; 53 a-=f; 54 if (!a) break; 55 } 56 } 57 return flow; 58 } 59 int Dinic(int s,int t) 60 { 61 this->s=s,this->t=t; 62 int ans=0; 63 while (bfs()) 64 { 65 for (int i=1;i<=n;i++) cur[i]=first[i]; 66 ans+=dfs(s,inf); 67 } 68 return ans; 69 } 70 }g; 71 int main() 72 { 73 scanf("%d%d",&n,&m); 74 for (int i=1;i<=n;i++) 75 { 76 scanf("%s",s+1); 77 for (int j=1;j<=m;j++) 78 mp[i][j]=s[j]=='*'; 79 } 80 for (int j=1;j<=m;j++) 81 { 82 belx[1][j]=mp[1][j]?++cntx:0; 83 for (int i=2;i<=n;i++) 84 if (mp[i][j]) 85 { 86 if (mp[i-1][j]) belx[i][j]=cntx; 87 else belx[i][j]=++cntx; 88 } 89 else belx[i][j]=0; 90 } 91 for (int i=1;i<=n;i++) 92 { 93 bely[i][1]=mp[i][1]?++cnty:0; 94 for (int j=2;j<=m;j++) 95 if (mp[i][j]) 96 { 97 if (mp[i][j-1]) bely[i][j]=cnty; 98 else bely[i][j]=++cnty; 99 } 100 else bely[i][j]=0; 101 } 102 g.n=cntx+cnty+2;int s=g.n-1,t=g.n; 103 for (int i=1;i<=n;i++) 104 for (int j=1;j<=m;j++) 105 if (mp[i][j]) g.insert(belx[i][j],bely[i][j]+cntx,1); 106 for (int i=1;i<=cntx;i++) g.insert(s,i,1); 107 for (int i=cntx+1;i<=cntx+cnty;i++) g.insert(i,t,1); 108 printf("%d\n",g.Dinic(s,t)); 109 return 0; 110 }