【备战秋招】每日一题:4月8日美团春招第二题:题面+题目思路 + C++/python/js/Go/java带注释

为了更好的阅读体检,为了更好的阅读体检,,可以查看我的算法学习博客第二题-必经之路

在线评测链接:P1167

题目内容

塔子哥的班主任最近组织了一次户外拓展活动,让班里的同学们一起去爬山。在路上,塔子哥看到了一棵漂亮的树,他对这棵树产生了浓厚的兴趣,开始观察并记录这棵树的一些特征。

塔子哥发现这棵树有 n 个节点,其中有一条边被特别标记了出来。他开始思考这条特殊的边在树上起到了什么样的作用,于是他想知道,经过这条选定边的所有树上简单路径中,最长的那条路径有多长,以便更好地理解这棵树的结构。

一条简单的路径的长度指这条简单路径上的边的个数。

输入描述

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

第二行 n-1 个整数,第 i 个数 p_i表示节点 i+1 和p_i之间有一条边相连。

第三行两个整数 x , y ,表示这条选定的边。保证这条边一定是树上的一条边。

对于全部数据, 2 \le n \le 10^51 \le p_i \le n1 \le x,y \le nx \neq 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

  1. 112. 路径总和

  2. 129. 求根到叶子节点数字之和

  3. 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
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

塔子哥学算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值