题意:
一个矩形中,有N个城市’*’,现在这n个城市都要覆盖无线,若放置一个基站,那么它至多可以覆盖相邻的两个城市。
问至少放置多少个基站才能使得所有的城市都覆盖无线?
思路:
二分图难的不是它的代码多难,而是它该怎么建立。像本题,初看好像与二分图无关,但是我们稍微转化一下,就发现,这就是一个二分图的问题了
首先,我们可以从第一个*,也就是城市开始标记。例如:
*** 标记为:123
oo* oo4
**o 56o
然后,我们就把123456分别存在v1 v2 中,所以对于3,它的匹配点为2、4,这时可以把32,34标记
剩下的就是基本的二分图思想了;
AC代码:
#include<iostream>
#include<string.h>
using namespace std;
int link[405][405]; //关系
int city[45][15]; //记录城市的位置
int vis[405],col[405]; //不解释!
int h,w,v1,v2,m,tot;
int dir[4][2]={1,0,-1,0,0,-1,0,1};
int dfs(int x)
{
for(int i=1;i<=v2;i++)
{
if(!vis[i]&&link[x][i])
{
vis[i]=1;
if(col[i]==0||dfs(col[i]))
{
col[i]=x;
return 1;
}
}
}
return 0;
}
int main()
{
int n,i,j;
cin>>n;
while(n--)
{
m=0;
tot=0;
memset(link,0,sizeof(link));
memset(city,0,sizeof(city));
memset(col,0,sizeof(col));
cin>>h>>w;
char c;
for(i=1;i<=h;i++)
for(j=1;j<=w;j++)
{
cin>>c;
if(c=='*'){
tot+=1;
city[i][j]=tot;
}
}
for(i=1;i<=h;i++)
for(j=1;j<=w;j++)
if(city[i][j]){
for(int k=0;k<4;k++){ //向四个方向找与当前位置匹配的点
int x=i+dir[k][0];
int y=j+dir[k][1];
if(city[x][y])
link[city[i][j]][city[x][y]]=1;
}
}
v1=v2=tot;
// cout<<tot<<endl;
for(i=1;i<=v1;i++)
{
memset(vis,0,sizeof(vis));
if(dfs(i))
m++;
}
// cout<<m<<endl;
cout<<tot-m/2<<endl; //为什么是这个自己想
}
return 0;
}