您的位置:首页 > 其它

bzoj 3175 攻击装置 | 二分图最大独立集

2015-11-16 10:40 417 查看
显然日字是从黑点到白点,所以黑白染色做独立集就行了。注意连边的时候要让它先和位于它下面的点匹配,因为下面的点未匹配的概率更大,dfs的深度也更小。我开始先匹配的上面的点,t了。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>

#define md
#define ll long long
#define inf (int) 1e9
#define eps 1e-8
#define N 210
#define M 40010
using namespace std;
struct yts { int x,t,ne; } e[8*M];
int g

;
char st

;
int v[M],vis[M],link[M];
int lx[8]={-1,-1,-2,-2,1,1,2,2,},ly[8]={2,-2,1,-1,2,-2,1,-1};
int num=0;
void put(int x,int y)
{
	num++; e[num].x=x; e[num].t=y;
	e[num].ne=v[x]; v[x]=num;
}
bool dfs(int x,int tm)
{
	if (vis[x]==tm) return 0;
	vis[x]=tm;
	for (int i=v[x];i;i=e[i].ne)
	{
		int y=e[i].t;
		if (!link[y]||dfs(link[y],tm)) 
		{
			link[y]=x;
			return 1;
		}
	}
	return 0;
}
void outit()
{
	for (int i=1;i<=num;i++) printf("%d %d\n",e[i].x,e[i].t);
}
int main()
{
	int n,ans=0;
	scanf("%d",&n);
	int tot=0;
	for (int i=1;i<=n;i++)
	  for (int j=1;j<=n;j++) 
	    g[i][j]=++tot;
	for (int i=1;i<=n;i++) scanf("%s",st[i]+1);
	for (int i=1;i<=n;i++)
	  for (int j=1;j<=n;j++)
	  {
	  	if (st[i][j]=='1') continue;
	  	ans++;
	  	if ((i&1)^(j&1)) continue;
	  	for (int k=0;k<=7;k++)
	  	{
	  		int x=i+lx[k],y=j+ly[k];
	  		if  (x<1||y<1||x>n||y>n||st[x][y]=='1') continue;
	  		put(g[i][j],g[x][y]);
	  	}
	  }
	for (int i=1;i<=n;i++)
	  for (int j=1;j<=n;j++)
	  {
	  	if (st[i][j]=='1') continue;
	  	if ((i&1)^(j&1)) continue;
	  	if (!link[g[i][j]]) ans-=dfs(g[i][j],g[i][j]);
	  }
	//outit();
	printf("%d\n",ans);
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: