使用邻接表-树上漫步

阅读量: 34 编辑

小 A 有一棵 n 个结点的树,这些结点依次以 1, 2, ⋯, n 标号。

小 A 想在这棵树上漫步。具体来说,小 A 会从树上的某个结点出发,每⼀步可以移动到与当前结点相邻的结点,并且小 A 只会在偶数步(可以是零步)后结束漫步。

现在小 A 想知道,对于树上的每个结点,从这个结点出发开始漫步,经过偶数步能结束漫步的结点有多少个(可以经过重复的节点)。

【输入描述】

第一行,一个正整数 n。

接下来 n−1 行,每行两个整数 ui ,vi ,表示树上有⼀条连接结点 ui 和结点 vi 的边。

【输出描述】

一行,n 个整数。第 i 个整数表示从结点 i 出发开始漫步,能结束漫步的结点数量。

【数据范围】

保证 1 ≤ n ≤ 2×105

【输入样例】

4
1 3
3 2
4 3

【输出样例】

3 3 1 3

【题解图】

【参考程序】

// 爱码岛编程
#include <bits/stdc++.h>
using namespace std;

const int MAXN = 2e5 + 10;
vector<int> adj[MAXN]; // 邻接表
int depth[MAXN];       // 记录每个结点的深度
int evenCnt = 0;       // 深度是偶数的结点数量
int oddCnt = 0;        // 深度奇数的结点数量

// 深度优先遍历
void dfs(int u, int parent, int d) {
    depth[u] = d; // 记录当前结点的深度
    if (d % 2 == 0) {
        evenCnt++;
    } else {
        oddCnt++;
    }
    for (int i = 0; i < adj[u].size(); i++) {
        int v = adj[u][i];
        if (v != parent) {
            dfs(v, u, d + 1);
        }
    }
}

int main() {
    int n;
    cin >> n;

    // 读取树的边并建立邻接表
    for (int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    // 从结点 1 开始 DFS 遍历,深度从 0 开始
    dfs(1, -1, 0);

    for (int i = 1; i <= n; i++) {
        if (depth[i] % 2 == 0) {
            cout << evenCnt << " ";
        } else {
            cout << oddCnt << " ";
        }
    }

    return 0;
}
爱码岛编程公众号
试卷资料
爱码岛编程小程序
在线刷题
苏ICP备13052010号
©2023 南京匠成信息科技有限公司