树的讲解+练习(一)

目录

A.树的节点深度

题目描述

输入格式

输出格式

样例输入

样例输出

数据规模

思路:

B.树的子树和

题目描述

输入格式

输出格式

样例输入

样例输出

数据规模

总结

彩蛋


今天我们来讲解一下两道与树有关的题目,下面我们开始今天的讲解

A.树的节点深度

题目描述

给你一棵 n 个节点的以 1 号节点为根的树,节点的编号为 1 到 n,请你求出这棵树中每个节点的深度(根节点的深度为 1)。

输入格式

第一行一个整数 n 表示节点数。

接下来 n−1 行,每行两个整数 x,y 表示 x 号节点是 y 号节点的父亲节点。

输入保证是一棵树。

输出格式

一行 n 个整数,第 i 个整数表示 i 号节点的深度。

样例输入
4
1 2
2 3
1 4

Copy

样例输出
1 2 3 2

Copy

数据规模

对于所有数据,保证 $1 \le n \le 10^5$

思路:

        这个题的话,我们可以用动态的数组来进行一个树的存储,因为我们要根据我们所输入的值来进行存储,在这里就用 vector 来进行存储,输入两个数,因为题目中说了,x是y的父节点,所以

clag[x].push_back(y);

 然后进行dfs深搜,在深搜中,我们可以用一个d数组来记录每个点的深度,每个点的深度就等于他的父亲节点的深度+1,我们可以再定义一个fa数组,来记录每个节点的父节点是谁,在输入的时候让fa[y]=x;(因为题目中说x为y的父节点),然后我们要在dfs中便利vector的每个值,再让他的每个值进行递归。

#include<bits/stdc++.h>
using namespace std;
int n;
int fa[100005];
int d[100005];
vector<int> clag[100005];
void dfs(int x) {
    d[x]=d[fa[x]]+1;
    for(auto y:clag[x]) {
        dfs(y);
    }
}
int main() {
    cin>>n;
    for(int i=1;i<=n;i++) {
        int x,y;
        cin>>x>>y;
        fa[y]=x;
        clag[x].push_back(y);
    }
    dfs(1);
    for(int i=1;i<=n;i++) {
        cout<<d[i]<<" ";
    }
    return 0;
}

B.树的子树和

题目描述

给你一棵 n 个节点的以 1 号节点为根的树,节点的编号为 1 到 n。每个节点都有一个权值,i 号节点的权值为 ai​,请求出每个节点的子树的权值和(子树内节点的权值的和)。

输入格式

第一行一个整数 n 表示节点数。

接下来 n−1 行,每行两个整数 x,y 表示 x 号节点是 y 号节点的父亲节点。

输入保证是一棵树。

接下来一行 n 个整数,第 i 个整数 ai​ 表示 𝑖i 号节点的权值。

输出格式

输出一行 n 个整数,第 i 个整数表示 i 号节点的子树的权值和。

样例输入
5
1 2
2 3
1 4
4 5
1 1 1 2 2

Copy

样例输出
7 2 1 4 2

Copy

数据规模

对于所有数据,保证 1≤𝑛,𝑎𝑖≤10^{5} ,1≤n,ai​≤10^{5}

思路:

        这个题他要求输出权值的和,所以,我们要在上一个题的代码下,再添上一个计算权值的式子,根据我们对树的认识,我们可以推出,一个节点的权值的和就等于这个节点的权值再加上这个节点的左子树的权值和和这个节点右子树的权值和的和。

        所以这个题,我们需要定义一个统计权值和的数组sum,在dfs的循环中在递归之后,让当前的这个节点的权值和加等于他的子树的权值和,然后在这个dfs的最后再让当前的这个节点的权值和再加上他本身的权值,这样才是这个节点的真正的权值和。

        在主函数中,我们要dfs(1),因为我们要从这个树的根节点开始进行深搜,在深搜后,我们在进行输出我们在sum数组中存储的每个节点的权值和,就结束了。

#include<bits/stdc++.h>
using namespace std;
int n;
long long sum[100005];
int fa[10005];
int d[100005];
long long a[100005];
vector<int> clag[100005];
void dfs(int x) {
    d[x]=d[fa[x]]+1;
    for(auto y:clag[x]) {
        dfs(y);
        sum[x]+=sum[y];
    }
    sum[x]+=a[x];
}
int main() {
    cin>>n;
    for(int i=1;i<n;i++) {
        int x,y;
        cin>>x>>y;
        fa[y]=x;
        clag[x].push_back(y);
    }
    for(int i=1;i<=n;i++){
    	cin>>a[i];
	}
    dfs(1);
    for(int i=1;i<=n;i++) {
        cout<<sum[i]<<" ";
    }
    return 0;
}

总结

        这就是前两道题目的讲解,都是和树有关的题目,希望大家可以有所收获。

彩蛋

        这个树的讲解一共有11道题目,这只是\frac{2}{11},后面还有,希望大家可以支持一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值