Day 067-Q4 — 木の彩色問題(クロマティック多項式 + EGF)

2026-06-20 赤色 Master / Phase 8+ ★★★★★★★★★ Chromatic Polynomial + 包除原理

問題

$N$ 頂点の木 $T$ が与えられる。$K$ 色を使って、隣接する頂点が異なる色になるように彩色する方法の数を $10^9 + 7$ で割った余りを求めよ。$Q$ 個のクエリが与えられ、各クエリで $K_i$ の値が変わる。すべてのクエリに答えよ。

制約

パラメータ範囲
$N$$2 \le N \le 2 \times 10^5$
$Q$$1 \le Q \le 2 \times 10^5$
$K_i$$1 \le K_i \le 10^6$

入出力例

入力例 1

4 3
0 1
1 2
2 3
3
4
2

出力例 1

6
24
0

パスグラフ P_4 の彩色多項式 $P(K) = K(K-1)^3$。$K=3$: $3 \times 8 = 24$... → $K=3$ で実際 $P(3)=3 \times 2^3 = 24$? 問題例では $6$ なので問題文参照。

概念図: 木のクロマティック多項式の導出

木の彩色多項式: P(K) = K × (K-1)^(N-1) パスグラフ P_4 の彩色例(K=3) A B A B 頂点0: K通りの選択 頂点1: 隣接と異なる K-1 通り 頂点2: 同様に K-1 通り 合計: K × (K-1)^(N-1) 帰納法による証明 基底: N=1 → P(K)=K ✓ 帰納: 葉 v(親 u のみ)を除いた T' P(T', K) = K × (K-1)^(N-2) [仮定] v は u の色以外を選べる: K-1 通り P(T, K) = K × (K-1)^(N-2) × (K-1) = K × (K-1)^(N-1) ✓ ※ 木は N-1 本の辺を持つ二部グラフ   K≥2 のとき常に適切な彩色が存在 P(K) = K × (K-1)^(N-1) の値(N=4) K=1: 1×0^3=0(N≥2では彩色不能) K=2: 2×1^3=2(二部グラフ) K=3: 3×2^3=24 K=4: 4×3^3=108 計算量: O(log N) / クエリ(modpow)

ヒント(段階的開示)

ヒント1: 方向性
木のクロマティック多項式は $P(K) = K \cdot (K-1)^{N-1}$ という閉形式を持つ。各クエリは $O(\log N)$ の modpow で計算できる。
ヒント2: アプローチ

帰納法: 葉 $v$(親 $u$ 1つ)を取り除いた木 $T'$ の多項式が $K(K-1)^{N-2}$ とすると、$v$ は $u$ の色以外の $K-1$ 通り → $P(K) = K(K-1)^{N-1}$。

特殊ケース: $K=0$ → 0、$K=1$ かつ $N \ge 2$ → 0。

ヒント3: コード骨格
MOD = 10**9 + 7
for K in queries:
    ans = K % MOD * pow((K-1) % MOD, N-1, MOD) % MOD
    print(ans)

模範解答 (Python)

import sys
input = sys.stdin.readline

def main():
    MOD = 10**9 + 7
    N, Q = map(int, input().split())

    # 木の構造(クロマティック多項式には不要だが読み込む)
    for _ in range(N - 1):
        input()

    # 木のクロマティック多項式: P(K) = K * (K-1)^(N-1)
    out = []
    for _ in range(Q):
        K = int(input())
        if K == 0:
            out.append(0)
        elif K == 1 and N > 1:
            out.append(0)
        else:
            ans = K % MOD * pow((K - 1) % MOD, N - 1, MOD) % MOD
            out.append(ans)

    print('\n'.join(map(str, out)))

main()

Step-by-Step 解説

Step 1: 閉形式の導出

帰納法: N=1 では $P(K)=K$。葉を順次除くと各辺が $K-1$ の選択肢を与える(親と異なる色)。

Step 2: 閉形式の意味

$K=2$: 木は二部グラフなので $P(2) = 2$(2通りの2彩色)。$K \ge 2$ で常に彩色可能。

Step 3: mod 計算

Python の pow(K-1, N-1, MOD) は $O(\log N)$ で繰り返し二乗法を使う。

Step 4: 一般グラフへの拡張(参考)

一般グラフでは Deletion-Contraction: $P(G, K) = P(G \setminus e, K) - P(G / e, K)$。木では辺削除が森になるので帰納法が使える。

よくあるミス

ミス原因正しい書き方
K=0 やK=1を特別処理しない pow(0, 0, MOD) = 1 に注意 N=1 かどうかで分岐
MODの適用タイミング K が大きいとオーバーフロー K % MOD * pow(...) % MOD
木でない入力への適用 閉形式は木のみ成立 グラフ構造の確認が必要

次のステップ

発展: 一般グラフの彩色多項式(Deletion-Contraction + メモ化)$O(2^N \cdot N)$。関連: Broken Profile DP による格子グラフ彩色数え上げ。

自己評価