bzoj2150 部落战争

题目链接:bzoj2150

题目大意:

男主要占领A国。A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧。男主有一些军队,约定: 
1. 每支军队可以从任意一个城镇出发,只能从上往向下征战,不能回头。途中只能经过城镇,不能经过高山深涧。 
2. 如果某个城镇被某支军队到过,则其他军队不能再去那个城镇了。 
3. 每支军队都可以在任意一个城镇停止征战。 4. 所有军队都很奇怪,他们走的方法有点像国际象棋中的马。不过马每次只能走1*2的路线,而他们只能走R*C的路线。
假设每支军队都能顺利占领这支军队经过的所有城镇,问男主至少要多少支军队才能完成统一全国的大业。


题解:

求最大点独立集

跟bzoj3175差不多,把能走到的互相连边构图,求个最大点独立集。于是上匈牙利跑最大匹配,最后用总点数减掉就好了。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 3000

struct node
{
	int x,y,next;
}a[maxn*4];int len,first[maxn];
int tim,ask[maxn],bf[maxn];
int map[60][60];
void ins(int x,int y)
{
	++len;a[len].x=x;a[len].y=y;
	a[len].next=first[x];first[x]=len;
}
bool ffind(int x)
{
	for (int i=first[x];i!=-1;i=a[i].next)
	 if (ask[a[i].y]!=tim)
	 {
		int y=a[i].y;
		ask[y]=tim;
		if (bf[y]==-1 || ffind(bf[y]))
		{
			bf[y]=x;
			return true;
		}
	 }
	return false;
}
int main()
{
	int n,m,r,c,i,j,ans,num;char x;
	scanf("%d%d%d%d",&n,&m,&r,&c);
	num=0;memset(map,0,sizeof(map));
	len=0;memset(first,-1,sizeof(first));
	for (i=1;i<=n;i++)
	{
		scanf("
");
		for (j=1;j<=m;j++)
		{
			scanf("%c",&x);
			if (x=='.') map[i][j]=++num;
		}
	}
	for (i=1;i<=n;i++)
	 for (j=1;j<=m;j++)
	  if (map[i][j])
	  {
		  if (map[i+r][j+c]) ins(map[i][j],map[i+r][j+c]);
		  if (map[i+r][j-c]) ins(map[i][j],map[i+r][j-c]);
		  if (map[i+c][j+r]) ins(map[i][j],map[i+c][j+r]);
		  if (map[i+c][j-r]) ins(map[i][j],map[i+c][j-r]);
	  }
	tim=ans=0;memset(ask,0,sizeof(ask));
	memset(bf,-1,sizeof(bf));
	for (i=1;i<=num;i++)
	{
		tim++;
		if (ffind(i)) ans++;
	}
	ans=num-ans;
	printf("%d
",ans);
	return 0;
}


原文地址:https://www.cnblogs.com/Euryale-Rose/p/6527798.html