【POJ 3020】Antenna Placement(二分图匹配)

时间:2023-03-09 00:31:54
【POJ 3020】Antenna Placement(二分图匹配)

相当于用1*2的板覆盖给定的h*w的格子里的点,求最少的板。
可以把格子相邻的分成两个集合,如下图,0为一个集合,1的为一个,也就是(行数+列数)为奇数的是一个集合,为偶数的为另一个集合。
1010101
0101010
1010101
两个集合分别代表男和女,能不能结婚,首先要看是不是异性,然后看是不是相邻的。所以就是用二分图匹配了。g[i][j]>0的表明i和j是相邻的。
找出最大的配对数,然后总共需要的板就是点的总数-配对的对数。

#include<cstdio>
#include<cstring>
#define N 500
int t,ans,h,w,n,m,u[N],link[N],g[N][N],b[][];
char c;
bool find(int a)
{
for(int i=; i<=n; i++)
if(g[a][i]&&!u[i])
{
u[i]=;
if(!link[i]||find(link[i]))
{
link[i]=a;
return true;
}
}
return false;
}
int main()
{
scanf("%d",&t);
while(t--)
{
n=m=ans=;
memset(g,,sizeof g);
memset(b,,sizeof b);
memset(link,,sizeof link);
scanf("%d%d ",&h,&w);
for(int i=; i<=h; i++)
{
for(int j=; j<=w; j++)
if((c=getchar())=='*')
if((i+j)&)
{
b[i][j]=++n;
g[b[i-][j]][b[i][j]]=b[i-][j];
g[b[i][j-]][b[i][j]]=b[i][j-];
}
else
{
b[i][j]=++m;
g[b[i][j]][b[i-][j]]=b[i-][j];
g[b[i][j]][b[i][j-]]=b[i][j-];
}
getchar();
}
for(int i=; i<=m; i++)
{
memset(u,,sizeof(u));
if(find(i))
ans++;
}
printf("%d\n",n+m-ans);
}
return ;
}