zoukankan      html  css  js  c++  java
  • agc025_d Choosing Points

    agc025_d Choosing Points

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

    UKeeHg.png

    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
    ",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("---
    ");
    		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
    ",S[i][j].fi,S[i][j].se);
    		return 0;
    	}
    	assert(0);
    }
    
  • 相关阅读:
    HttpWebRequest 的一个 异步封装
    AcWing 6 多重背包问题III【单调对列优化】
    AcWing 8. 二维费用的背包问题
    AcWing 1019. 庆功会
    P1421 小玉买文具
    P5709 【深基2.习6】Apples Prologue / 苹果和虫子
    P2181 对角线
    AcWing 1020. 潜水员
    AcWing 1013. 机器分配【分组背包+求方案数】
    AcWing 7. 混合背包问题
  • 原文地址:https://www.cnblogs.com/ljzalc1022/p/13279117.html
Copyright © 2011-2022 走看看