[简单思维] 题解 ThREE

[简单思维] 题解 ThREE

题目链接

这题自己没有独立想出来啊啊啊啊啊。

题目分析

首先考虑何时满足 \(p_i+p_j\equiv 0\pmod 3\) 或者 \(p_i\times p_j\equiv 0\pmod 3\) ,如果 \(p_i\bmod 3=0\) 或者 \(p_j\bmod 3=0\) 时显然满足,否则 \(p_i\bmod 3=1\) 并且 \(p_j\bmod 3=2\)\(p_i\bmod 3=2\) 并且 \(p_j\bmod 3=1\) ,类似二分图,但是不允许我们连完所有边 \((i,j)\)\(\mbox{dis}(i,j)=3\) )后二分图染色,如果直接在树上面进行二分图染色,那么也满足 \(i,j(\mbox{dis}(i,j)=3)\) 不同色,所以不妨先在树上面进行一波二分图染色。

假设黑色节点数量为 \(b\) ,白色节点数量为 \(w\) ,分类讨论:

  • 如果 \(b>\lfloor\frac{n}{3}\rfloor\) 并且 \(w> \lfloor\frac{n}{3}\rfloor\) ,此时必然可以将所有模 \(3\)\(1\) 的数分配给黑色节点,所有模 \(3\)\(2\) 的数分配给白色节点,剩下的数模 \(3\)\(0\) ,就可以任意分配了。
  • 如果 \(b\le \lfloor\frac{n}{3}\rfloor\) ,此时就可以给所有黑色节点分配到模 \(3\)\(0\) 的数,剩下的数就随意分配即可。
  • 如果 \(w\le \lfloor\frac{n}{3}\rfloor\) ,和 \(b\le \lfloor\frac{n}{3}\rfloor\) 一样。

我自己主要是 \(b\le \lfloor\frac{n}{3}\rfloor\) 的情况没有想到如何处理。

参考代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ch() getchar()
#define pc(x) putchar(x)
using namespace std;
template<typename T>void read(T&x){
	static char c;static int f;
	for(c=ch(),f=1;c<'0'||c>'9';c=ch())if(c=='-')f=-f;
	for(x=0;c>='0'&&c<='9';c=ch())x=x*10+(c&15);x*=f;
}
template<typename T>void write(T x){
	static char q[65];int cnt=0;
	if(x<0)pc('-'),x=-x;
	q[++cnt]=x%10,x/=10;
	while(x)
		q[++cnt]=x%10,x/=10;
	while(cnt)pc(q[cnt--]+'0');
}
const int maxn=200005;
struct Edge{
	int v,nt;
	Edge(int v=0,int nt=0):
		v(v),nt(nt){}
}e[maxn*2];
int hd[maxn],num;
void qwq(int u,int v){
	e[++num]=Edge(v,hd[u]),hd[u]=num;
}
int B,W,dp[maxn];
void dfs(int u,int fa){
	if(dp[u]&1)++B;else ++W;
	for(int i=hd[u];i;i=e[i].nt){
		int v=e[i].v;
		if(v==fa)continue;
		dp[v]=dp[u]+1;dfs(v,u);
	}
}
int p[maxn],vis[maxn];
int main(){
	int n;read(n);
	for(int i=1;i<n;++i){
		int u,v;
		read(u),read(v);
		qwq(u,v);qwq(v,u);
	}
	dfs(1,0);int nd3=n/3;
	if(B>nd3&&W>nd3){
		int n1=1,n2=2,n3=3;
		for(int i=1;i<=n;++i){
			if(dp[i]&1){
				if(n1<=n)p[i]=n1,n1+=3;
				else p[i]=n3,n3+=3;
			}
			else{
				if(n2<=n)p[i]=n2,n2+=3;
				else p[i]=n3,n3+=3;
			}
		}
	}
	else{
		int spe=(B>W),n3=3;
		for(int i=1;i<=n;++i){
			if((dp[i]&1)^spe){
				p[i]=n3;vis[n3]=true;n3+=3;
			}
		}
		int no=1;
		for(int i=1;i<=n;++i){
			if(!((dp[i]&1)^spe)){
				while(vis[no])++no;p[i]=no;++no;
			}
		}
	}
	for(int i=1;i<=n;++i)
		write(p[i]),pc(" \n"[i==n]);
	return 0;
}

posted @ 2020-11-04 20:01  xiaolilsq  阅读(93)  评论(0编辑  收藏  举报