码迷,mamicode.com
首页 > 其他好文 > 详细

agc025_d Choosing Points

时间:2020-07-10 15:36:35      阅读:66      评论:0      收藏:0      [点我收藏+]

标签:抽屉原理   ios   http   iostream   cto   lang   二分   deb   pre   

agc025_d Choosing Points

https://atcoder.jp/contests/agc025/tasks/agc025_d

技术图片

Tutorial

https://img.atcoder.jp/agc025/editorial.pdf

我们要解决的问题实际上是

有两个大小为\(V\)的二分图,需要找到一个大小为\(\dfrac V4\)的点集,满足这个点集在两张图上都是独立集

首先,证明若在两个距离为\(D\)的点之间连一条边,那么这会形成一张二分图.

\(D\)是奇数,那么若\((x,y),(x+s,y+t)\)之间距离为\(D\),那么\(s^2+t^2\)距离为奇数,也就是说\(s,t\)的奇偶性不同,所以我们可以根据\(x+y\)的奇偶性也就是棋盘染色将其分为二分图.

\(D\)是偶数,那么棋盘染色后,有连边的点一定颜色相同,不妨考虑所有黑色的点,可以旋转\(45\)度后将其看做一个方格图,且此时距离为\(d\)相当于原图上距离为\(\sqrt 2d\) ,那么此时的\(D\)变为\(\dfrac D2\).那么不断递归就会变成\(D\)为奇数的情况.

证毕

回到我们转化后的问题,可以对两个二分图分别黑白染色,于是每个点可以根据它在两张图上的颜色分为\(4\)类,根据抽屉原理,一定存在一类点数量大于等于\(\dfrac V4\),而且根据黑白染色的定义,在同一集合中的点一定是独立集.于是就找到了答案

Code

#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define fi first
#define se second
using namespace std;
inline char gc() {
	return getchar();
	static char buf[100000],*l=buf,*r=buf;
	return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
}
template<class T> void rd(T &x) {
	x=0; int f=1,ch=gc();
	while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=gc();}
	while(ch>=‘0‘&&ch<=‘9‘){x=x*10-‘0‘+ch;ch=gc();}
	x*=f;
}
const int maxn=300+5;
int n,D1,D2;
struct Solver {
	int col[maxn<<1][maxn<<1];
	vector< pair<int,int> > V;
	void init(int D) {
		for(int i=0;i<2*n;++i) for(int j=0;j<2*n;++j) {
			if(i*i+j*j==D) {
				V.push_back(make_pair(i,j));
				V.push_back(make_pair(-i,j));
				V.push_back(make_pair(i,-j));
				V.push_back(make_pair(-i,-j));
			}
		}
	}
	void dfs(int x,int y,int c) {
		if(col[x][y]!=-1) return;
//		debug("%d %d %d\n",x,y,c);
		col[x][y]=c;
		for(int i=0;i<V.size();++i) {
			int _x=x+V[i].fi,_y=y+V[i].se;
			if(_x<0||_x>=n*2) continue;
			if(_y<0||_y>=n*2) continue;
			dfs(_x,_y,c^1);
		}
	}
	void sol(int D) {
		init(D);
		memset(col,-1,sizeof(col));
//		debug("---\n");
		for(int i=0;i<2*n;++i) for(int j=0;j<2*n;++j) if(col[i][j]==-1) {
			dfs(i,j,0);
		}
	}
} solver[2];
int main() {
	rd(n),rd(D1),rd(D2);
	solver[0].sol(D1),solver[1].sol(D2);
	vector< pair<int,int> > S[4];
	for(int i=0;i<2*n;++i) for(int j=0;j<2*n;++j) {
		S[solver[0].col[i][j]<<1|solver[1].col[i][j]].push_back(make_pair(i,j));
	}
	for(int i=0;i<4;++i) if(S[i].size()>=n*n) {
		for(int j=0;j<n*n;++j) printf("%d %d\n",S[i][j].fi,S[i][j].se);
		return 0;
	}
	assert(0);
}

agc025_d Choosing Points

标签:抽屉原理   ios   http   iostream   cto   lang   二分   deb   pre   

原文地址:https://www.cnblogs.com/ljzalc1022/p/13279117.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!