bzoj 2150 部落战争(二分图匹配)

版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎添加友链。 https://blog.csdn.net/zzk_233/article/details/82939523

 最坏情况下每个’.’都要放一支军队,但是事实是有些’.’可以不放因为可以利用前面的军队移动过来,

所以答案就可以表示为’.’的数量减掉最多可以节约多少只军队。

由于每个’.’只能最多有一个前驱和一个后继(由一个点转移而来,也只能转移向一个点),

所以我们将原图拆点,每个格点拆成一个入点和一个出点,出点向可到达的入点连边,就形成了一个二分图,

求此图的最大匹配即为最多可节约的军团数量。(PS:匈牙利算法真好用)。
 

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
char s[55][55];
int n,m,r,c,x,y,ans;
int check(int a,int b)
{
	if(a<=n&&a>=1&&b<=m&&b>=1)
	{
		return 1;
	}
	return 0;
}
int has(int a,int b)
{
	return (a-1)*m+b;
}
struct node
{
	int to;
	int nxt;
}edge[20005];
int head[3005];
int cnt = 1;
void init()
{
	memset(head,-1,sizeof(head));
}
void add(int from,int to)
{
	edge[cnt].to = to;
	edge[cnt].nxt = head[from];
	head[from] = cnt++;
}
int used[3005],girl[3005];
int Hungary(int u)
{
	used[u] = 1;
	for(int i = head[u];i != -1;i = edge[i].nxt)
	{
		int to = edge[i].to;
		if(!used[to])
		{
			used[to] = 1;
			if(!girl[to] || Hungary(girl[to]))
			{
				girl[to] = u;
				return 1;
			}
		}
	}
	return 0;
}
int main()
{
	scanf("%d%d%d%d", &n, &m, &r, &c);
	init();
	int ru[4][2]={r,c,r,-c,c,r,c,-r};
	for(int i = 1;i <= n;i++)scanf("%s",s[i]+1);
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= m;j++)
		{
			if(s[i][j] == '.')
			{
				for(int k = 0;k < 4;k++)
	            {
	                x=i+ru[k][0];
	                y=j+ru[k][1];
	                if(check(x,y) && s[x][y] == '.')
	                {
	                	add(has(i,j),has(x,y));
	                }
	            }
			}
		}
	} 
 	for(int i = 1;i <= n;i++)
 	{
	 	for(int j = 1;j <= m;j++)
	 	{
	 		if(s[i][j] == '.')
	 		{
		 		memset(used,0,sizeof(used));
		 		if(Hungary(has(i,j)) == 0)
		 		{
		 			ans++;
		 		}
		 	}
	 	}
	 }
	 printf("%d",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zzk_233/article/details/82939523