← 返回题目页

A1905 [GESP-6.2503.T1] 树上漫步

标程

#include <bits/stdc++.h>
using namespace std;

// [GESP-6.2503.T1] 树上漫步
//
// 从 u 出发走偶数步能到达 v <=> dist(u, v) 是偶数:
//   * 必要性:每走一步颜色(0/1 染色)翻转一次,偶数步后颜色与起点相同;
//   * 充分性:沿最短路走过去(偶数步),想多走就「来回多走几步」,每多走 2 步仍然到 v。
//
// 树是二分图:把结点染成 0/1 两色(相邻不同色),
// 则 dist(u, v) 为偶数 <=> u 与 v 同色。
// 所以答案就是「u 所在颜色类的结点个数」。

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;

    vector<vector<int>> g(n + 1);
    for (int i = 0; i < n - 1; i++) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    // BFS 染色,同时统计两种颜色各有多少结点
    vector<int> col(n + 1, -1);
    int cnt[2] = {0, 0};
    queue<int> q;
    col[1] = 0;
    q.push(1);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        cnt[col[u]]++;
        for (int v : g[u]) {
            if (col[v] == -1) {
                col[v] = col[u] ^ 1;
                q.push(v);
            }
        }
    }

    for (int i = 1; i <= n; i++) {
        cout << cnt[col[i]] << (i == n ? '\n' : ' ');
    }
    return 0;
}

动画演示