AT274の技術だったりなかったり

あっとのTECH LOG

競プロのこととか技術のこととか。たまに日常を書きます。

日立コン2020 C - ThREE

問題原文

atcoder.jp

問題要旨

 N 頂点の木がある。以下の条件を満たすよう、各頂点に1から  N までの数を当てはめよ。

  • 距離が3である頂点のペアに書かれている数の和もしくは積が3の倍数

  •   1 \leq N \leq 10^{5}

解法

超絶怒涛の神良問(解けなかったけど) 。

3, 6, 9などはどれとでもペアになれる便利な数。
1, 4, 7... などの3で割って1余るものは、2, 5, 8... などの3で割って2余るものとペアになる必要がある。逆もしかり。

というわけで、「木を二分グラフに見立てて、赤色と青色の二色に塗り分ける」
すると、赤色に1, 4, 7...、青色に2, 5, 8...、足りない部分に2, 6, 9...を当てはめればだいたいうまくいく。

うまくいかないパターンとして、ウニグラフのような、「ピンポイントに3をおく必要があるもの」が考えられる。
実は、普通に考えれば、赤色で塗った頂点の数 or 青色で塗った頂点の数が3, 6, 9...の数より少ないならば、3, 6, 9...をそのような色にまとめて当てはめてしまえることがわかる。

大きくパターンは2種類(赤と青の入れ替えを考えれば3種類)で、

  1. 「1, 4, 7...」と「2, 5, 8...」で分けて塗り、足りない部分に「3, 6, 9...」を当てはめる
  2. 「3, 6, 9...」と「1, 4, 7, 2, 5, 8...」 に分けて塗る(積を3の倍数にしていく)

がある。

実装

N = int(input())
T = [[] for _ in range(N)]
for _ in range(N - 1):
    a, b = map(int, input().split())
    a, b = a - 1, b - 1
    T[a].append(b)
    T[b].append(a)


colors = [-1] * N
stack = [(0, 0)]
while stack:
    n, color = stack.pop()
    colors[n] = color
    for to in T[n]:
        if colors[to] != -1:
            continue
        stack.append((to, color ^ 1))


# あまり1、あまり2、あまり0になるように並び替え
X = [[] for _ in range(3)]
for n in range(1, N + 1):
    X[n % 3].append(n)
X.append(X[0])
del X[0]


ans = []
x12, x3 = X[0] + X[1], X[2]
if colors.count(0) <= N // 3:
    for color in colors:
        if color == 0:
            ans.append(x3.pop())
        elif x12:
            ans.append(x12.pop())
        else:
            ans.append(x3.pop())

elif colors.count(1) <= N // 3:
    for color in colors:
        if color == 1:
            ans.append(x3.pop())
        elif x12:
            ans.append(x12.pop())
        else:
            ans.append(x3.pop())

else:
    for color in colors:
        if X[color]:
            ans.append(X[color].pop())
        else:
            ans.append(X[2].pop())

print(' '.join(map(str, ans)))

感想

「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」「木は二分グラフ!!!」