为了更好的阅读体检,为了更好的阅读体检,,可以查看我的算法学习博客第二题-必经之路
在线评测链接:P1167
题目内容
塔子哥的班主任最近组织了一次户外拓展活动,让班里的同学们一起去爬山。在路上,塔子哥看到了一棵漂亮的树,他对这棵树产生了浓厚的兴趣,开始观察并记录这棵树的一些特征。
塔子哥发现这棵树有 n 个节点,其中有一条边被特别标记了出来。他开始思考这条特殊的边在树上起到了什么样的作用,于是他想知道,经过这条选定边的所有树上简单路径中,最长的那条路径有多长,以便更好地理解这棵树的结构。
一条简单的路径的长度指这条简单路径上的边的个数。
输入描述
第一行一个整数 n ,表示树的节点个数。
第二行 n-1 个整数,第 i 个数 表示节点 i+1 和之间有一条边相连。
第三行两个整数 x , y ,表示这条选定的边。保证这条边一定是树上的一条边。
对于全部数据, ,,, 。
保证输入数据正确描述一棵树,并且( x, y ) 是树上的条边。
输出描述
输出一行,一个整数,表示所有经过选定边的树上简单路径中,最长的那条的长度。
样例
输入
7 1 2 3 4 5 3 3 7
输出*
4
思路
树上dfs
由于是一棵树,所以将 (x,y) 这条边删除后,树就被拆分为两棵树。
接着分别以 x 和 y 为根对两棵子树 dfs 求出最大深度即可。
时间复杂度:O(n)
类似题目推荐
这道题是非常经典,也非常"裸"的树上dfs问题。LeetCode上有非常多的例题,并且在2023年春招过程中考了114514次。望周知。
LeetCode
-
112. 路径总和
-
129. 求根到叶子节点数字之和
-
236. 二叉树的最近公共祖先
CodeFun2000
难度依次递增
1.P1141 2023.04.01-美团-第五题-染色の树
2.P1224 携程 2023.04.15-春招-第三题-魔法之树
3.P1159. 2022年清华大学(深圳)保研夏令营机试题-第一题-树上计数
4.P1196 华为 2023-04-19-第二题-塔子哥出城
5.P1044. 拼多多内推笔试-2023.2.22.投喂珍珠
6.P1193. 腾讯音乐 2023.04.13-暑期实习-第二题-价值二叉树
更多请见:知识点分类-训练-深度优先搜索专栏
代码
CPP
#include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; // 读入 vector<vector<int>> g(n); for (int i = 2; i <= n; ++i) { int p; cin >> p; g[p - 1].emplace_back(i - 1); g[i - 1].emplace_back(p - 1); } // C++11特性:匿名函数 function<int(int,int)> dfs = [&](int u, int fa) { int res = 0; for (int v: g[u]) { if (v == fa) continue; res = max(res, dfs(v, u) + 1); } return res; }; int x, y; cin >> x >> y; x -= 1; y -= 1; // 拆成两部分dfs cout << dfs(x, y) + dfs(y, x) + 1 << "n"; return 0; }
python
# 读入 n = int(input()) p = list(map(int, input().split(" "))) g = [[] for i in range(n)] for i in range(2, n + 1): g[i - 1].append(p[i - 2] - 1) g[p[i - 2] - 1].append(i - 1) x, y = map(int, input().split(" ")) x -= 1 y -= 1 def dfs(u, fa): res = 0 for v in g[u]: if v == fa: continue res = max(res, dfs(v, u) + 1) return res # 根据题意拆成两部分 print(dfs(x, y) + dfs(y, x) + 1)Java
import java.util.*; public class Main { static List<List<Integer>> g; public static void main(String[] args) { // 读入 Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); g = new ArrayList<>(); for (int i = 0; i < n; i++) { g.add(new ArrayList<>()); } for (int i = 2; i <= n; i++) { int p = scanner.nextInt(); g.get(i - 1).add(p - 1); g.get(p - 1).add(i - 1); } int x = scanner.nextInt() - 1; int y = scanner.nextInt() - 1; // 根据题意拆成两部分dfs System.out.println(dfs(x, y) + dfs(y, x) + 1); } private static int dfs(int u, int fa) { int res = 0; for (int v : g.get(u)) { if (v == fa) { continue; } res = Math.max(res, dfs(v, u) + 1); } return res; } }
Js
process.stdin.resume(); process.stdin.setEncoding('utf-8'); let input = ''; process.stdin.on('data', (data) => { input += data; return; }); process.stdin.on('end', () => { const lines = input.trim().split('n'); const n = parseInt(lines[0]); const p = lines[1].split(' ').map(Number); const g = new Array(n + 5).fill(); for (var i = 1 ; i <= n ; i++) g[i] = []; for (let i = 2; i <= n ; i++) { g[i].push(p[i - 2]); g[p[i - 2]].push(i); } let [x, y] = lines[2].split(' ').map(Number); console.log(dfs(x, y , g) + dfs(y, x , g) + 1); }); function dfs(u, fa , g) { let res = 0; for (const v of g[u]) { if (v === fa) continue; res = Math.max(res, dfs(v, u , g) + 1); } return res; }
Go
package main import ( "bufio" "fmt" "os" ) func main() { sc := bufio.NewReader(os.Stdin) var n int fmt.Fscanln(sc, &n) edges := [][]int{} for i := 1; i < n; i++ { var pi int fmt.Fscan(sc, &pi) edges = append(edges, []int{i + 1, pi}) } fmt.Fscanln(sc) var x, y int fmt.Fscanln(sc, &x, &y) test14(n, edges, x, y) } func test14(n int, edges [][]int, x, y int) { // 建图 graph := map[int][]int{} for _, edge := range edges { graph[edge[0]] = append(graph[edge[0]], edge[1]) graph[edge[1]] = append(graph[edge[1]], edge[0]) } // 分别从 x, y 向两边延伸, 分别得到最长的, 相加 + 1 visitedMap := map[int]bool{} var dfs func(node int) int dfs = func(node int) int { if len(graph[node]) == 0 { return 1 } res := 0 for _, next := range graph[node] { if !visitedMap[next] { visitedMap[next] = true res = max(res, 1+dfs(next)) visitedMap[next] = false } } return res } visitedMap[x] = true visitedMap[y] = true resX, resY := dfs(x), dfs(y) fmt.Println(resX + resY + 1) } func max(a, b int) int { if a > b { return a } return b }