东方博宜OJ 2166:子树的大小及深度 ← 树形DP

【题目来源】
https://oj.czos.cn/p/2166

【题目描述】
现在有一棵 n 个结点的树,结点为这棵树的根,结点 1 的深度为 1,求出每棵子树的大小及每个结点的深度。比如,有如下图所示的树:

boyi2166

该树中:
结点 1 对应的子树大小为 6,深度为 1。
结点 2 对应的子树大小为 5,深度为 2。
结点 3 对应的子树大小为 1,深度为 3。
结点 4 对应的子树大小为 1,深度为 3。
结点 5 对应的子树大小为 2,深度为 3。
结点 6 对应的子树大小为 1,深度为 4。

【输入格式】
输入有 n 行。
第 1 行有一个整数 n,代表结点的数量,结点的编号为 1~n。(1≤n≤100)
接下来有 n-1 行,每行有 2 个整数 x,y,表示结点 x 和 y 之间有一条边。(不保证 x 是 y 的父)

【输出格式】
输出有 n 行。
第 i 行输出 2 个整数,分别是以编号 i 为根的子树的大小,以及编号 i 对应的结点的深度。

【输入样例】
6
1 2
5 2
2 3
4 2
5 6

【输出样例】
6 1
5 2
1 3
1 3
2 3
1 4​​​​​​​

【数据范围】
1≤n≤100

【算法分析】
本文代码通过 DFS 实现树形 DP 的核心思想。
树形 DP(动态规划)的核心思想是通过深度优先搜索(DFS)遍历树结构,自底向上计算每个节点的状态。

【算法代码】

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

const int N=105;
int e[N<<1],ne[N<<1],h[N],idx;
int a[N],dep[N],siz[N];

void add(int a,int b) {
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

int dfs(int u,int fa) {
    siz[u]=1;
    dep[u]=dep[fa]+1;
    for(int i=h[u]; i!=-1; i=ne[i]) {
        int j=e[i];
        if(j!=fa) siz[u]+=dfs(j,u);
    }
    return siz[u];
}

int main() {
    memset(h,-1,sizeof h);
    int n,x,y;
    cin>>n;
    for(int i=1; i<n; i++) {
        cin>>x>>y;
        add(x,y),add(y,x);
    }

    dfs(1,0);

    for(int i=1; i<=n; i++) {
        cout<<siz[i]<<" "<<dep[i]<<endl;
    }

    return 0;
}

/*
in:
6
1 2
5 2
2 3
4 2
5 6

out:
6 1
5 2
1 3
1 3
2 3
1 4
*/





【参考文献】
https://www.cnblogs.com/Ghost1GM/p/17580688.html
https://oj.czos.cn/p/2166




 

posted @ 2025-12-03 23:00  Triwa  阅读(11)  评论(0)    收藏  举报