Loading

AT5759 ThREE 题解

题面

solution

一道比较好的构造题。

距离为三的点对至少满足 \(p_i + p_j\)\(p_i \times p_j\) 其中一个为 \(3\) 的倍数。

不妨考虑什么时候距离为 \(3\) 的点对两个条件都不满足。

把总的数分为三类:

A: \(p_i \equiv 0~(mod~ 3)\)

B: \(p_i \equiv 1~(mod~ 3)\)

C: \(p_i \equiv 2~(mod~ 3)\)

发现只有 \(p_i \equiv 1~(mod~ 3)\)\(p_j\equiv 1 ~(mod~3)\) 或者 \(p_i \equiv 2~(mod~ 3)\)\(p_j\equiv 2 ~(mod~3)\) 这会同时不满足。

就考虑构造方案让这两种情况都不发生。

构造方案:对树进行黑白染色。

设黑色点的数量为 \(x\), 白色点的数量为 \(y\)

  • \(x > \lfloor \frac{n}{3} \rfloor\)\(y > \lfloor \frac{n}{3} \rfloor\) 时。

\(B\) 全为白点,\(C\) 全为黑点,显然,\(B, C\) 类肯定会全部被染完,剩下 \(A\) 类随便分就好了。

  • \(x \leq \lfloor \frac{n}{3} \rfloor\)

此时黑点全为 C 类,此时黑点会全被用完,剩下的全为白点就好了。

  • \(y \leq \lfloor \frac{n}{3} \rfloor\)

此时白点全为 C 类,此时白点会全被用完,剩下的全为黑点就好了。

所以一定可以构造出一组解满足条件。

code

/*
work by: Ariel_
Knowledge:
Time:
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int MAXM = 4e5 + 5, MAXN = 2e5 + 5;
int read() {
  int x = 0, f = 1; char c = getchar();
  while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
  while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
  return x * f;
}
int n, col[MAXN], cnt_1, cnt_0, Ans[MAXN];
struct edge{int v, nxt;}e[MAXM];
int E, head[MAXN];
void add_edge(int u, int v) {
  e[++E] = (edge){v, head[u]};
  head[u] = E;
}
void dfs(int x, int fa) {
   col[x] = col[fa] == 1 ? 0 : 1;
   col[x] == 1 ? cnt_1++:cnt_0++; 
   for (int i = head[x]; i; i = e[i].nxt) {
   	   int v = e[i].v;
   	   if(v == fa) continue;
   	   dfs(v, x);
   } 
}
int p_1 = 1, p_2 = 2, p_0 = 3;
int main(){
  n = read();
  for (int i = 1; i < n; i++) {
  	 int u = read(), v = read();
  	 add_edge(u, v), add_edge(v, u);
  }
  dfs(1, 1);
  for (int i = 1; i <= n; i++) {
  	if(cnt_1 > n / 3 && cnt_0 > n / 3) {
  	   if(col[i]) {
  	     if (p_1 <= n) Ans[i] = p_1, p_1 += 3;
		 else Ans[i] = p_0, p_0 += 3; 	
	   }
	   else {
	   	 if (p_2 <= n) Ans[i] = p_2, p_2 += 3;
	   	 else Ans[i] = p_0, p_0 += 3;
	   }	
	}
	else if(cnt_1 <= n / 3) {
	   if(!col[i]) {
	   	 if(p_1 <= n) Ans[i] = p_1, p_1 += 3;
	   	 else if(p_2 <= n) Ans[i] = p_2, p_2 += 3;
	   	 else Ans[i] = p_0, p_0 += 3;
	   }
	   else Ans[i] = p_0, p_0 += 3;
	}
	else if(cnt_0 <= n / 3){
	   if(col[i]) {
	   	 if(p_1 <= n) Ans[i] = p_1, p_1 += 3;
	   	 else if(p_2 <= n) Ans[i] = p_2, p_2 += 3;
	   	 else Ans[i] = p_0, p_0 += 3;
	   }
	   else Ans[i] = p_0, p_0 += 3;
	}
  }
  for (int i = 1; i <= n; i++) printf("%d ", Ans[i]);
  puts("");
  return 0;
}

posted @ 2021-10-18 08:40  Dita  阅读(33)  评论(0编辑  收藏  举报