题意
一个矩形中,有n个城市’*’,现在这n个城市都要覆盖无线,若放置一个基站,那么它至多可以覆盖相邻的两个城市。 问至少放置多少个基站才能使得所有的城市都覆盖无线?
分析
每一个城市都需要被一个基站覆盖,而一个基站最多覆盖两个城市。为了使基站的数量最少,我们可以考虑让尽可能多的基站覆盖两个城市。设最多能让a个基站覆盖两个城市,则一共需要 n-a个基站。问题转化为求这个a。这种覆盖方式是不是似曾相识?对了,就是二分图!对于每个矩阵中的点(i,j),若(i+j)&1 == 1 ,则涂成黑色,反之涂成白色。这样一来,对于每个矩阵中相邻的点,都是黑白形式,也就是说,都是涂成黑色的点连向涂成白色的点。到这一步,恭喜您成功获得二分图模型,这不就是求二分图的最大配对吗?不会二分图的请移步模板。
CODE
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<queue> #include<algorithm> #include<map> using namespace std; #define N 45 #define M N*N int H,W,k,tot,ans,cnt; int head[M],Next[M],ver[M]; int match[M],vis[M],v[N][N]; bool flag[M]; int dx[]={-1,0,1,0}; int dy[]={0,1,0,-1}; void add(int x,int y){ ver[++tot]=y; Next[tot]=head[x],head[x]=tot; } char c[N][N]; bool dfs(int x){ for(int i=head[x],y;i;i=Next[i]) if(!vis[y=ver[i]]){ vis[y]=1; if(!match[y]||dfs(match[y])){ match[y]=x; return true; } } return false; }//匈牙利板子 void init(){ ans=tot=cnt=0; memset(head,0,sizeof(head)); memset(flag,0,sizeof(flag)); memset(v,0,sizeof(v)); memset(match,0,sizeof(match)); }//极其重要的清零 int t; int main(){ scanf("%d",&t); while(t--){ scanf("%d%d",&H,&W); init(); for(int i=1;i<=H;++i) for(int j=1;j<=W;++j){ scanf(" %c",&c[i][j]); if(c[i][j]=='*') { v[i][j]=++cnt; if((i+j)&1) flag[cnt]=1; //将黑色的点区别出来 } } for(int i=1;i<=H;++i) for(int j=1;j<=W;++j) if(v[i][j]){ for(int k=0;k<4;++k){ int x=i+dx[k],y=j+dy[k]; if(v[x][y]) add(v[i][j],v[x][y]); }//四个方向都要看 } for(int i=1;i<=cnt;++i){ if(!flag[i]) continue; memset(vis,0,sizeof(vis)); if(dfs(i)) ++ans; } printf("%d\n",cnt-ans); } return 0; }View Code