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

news2024/11/16 13:27:30

为了更好的阅读体检,为了更好的阅读体检,,可以查看我的算法学习博客第五题-RGP种树

在线评测链接:P1170

题目描述:

塔子哥是一位著名的冒险家,他经常在各种森林里探险。今天,他来到了道成林,这是一片美丽而神秘的森林。在探险途中,他遇到了一棵 n 个节点的树,树上每个节点都被涂上了红、绿、蓝三种颜色之一。

塔子哥发现,如果这棵树同时存在一个红色节点、一个绿色节点和一个蓝色节点,那么我们就称这棵树是多彩的。很幸运,他发现这棵树最初就是多彩的。

但是,在探险的过程中,塔子哥发现这棵树上有一条边非常重要,如果砍掉这条边,就可以把这棵树分成两个部分。他想知道,有多少种砍法可以砍掉这条边,使得砍完之后形成的两棵树都是多彩的。

输入描述

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

第二行 n-1 个整数 p_2,p_3,...,p_np_i表示树上 i 和 p 两点之间有一条边。保证给出的定是一棵树。

第三行一个长度为 n 的字符串,第 i 个字符表示第 i 个节点的初始颜色。其中 R 表示红色, G 表示绿色, B 表示蓝色。

保证字符串只由这三种大写字母构成对于全部数据, 3\le n\le 10^5

输出描述

输出一行,一个正整数,表示答案。

样例

输入

7
​
1 2 3 1 5 5
​
GBGRRBB

输出

1

思路

树的遍历 + DFS

考虑以 1 号点为根构造一棵树。

对于每条边 u-v,其中 v 是 u 的儿子。

则砍掉 u-v 这条边,将树分为了 以 v 为根的子树以 0 为根的树上砍掉以 v 为根的子树 这两部分。

故需要知道这两部分的 RGB 的数量。

先一遍 dfs 统计以每个点为根的子树中 RGB 的数量,再一遍 dfs 枚举断点每条边,然后统计两个新的部分中 RGB 的数量。

时间复杂度:O(n)

类似题目推荐

点评:树上dfs问题在LeetCode上有非常多的例题,并且在2023年春招过程中考了114514次。望周知。

LeetCod

  1. 589. N 叉树的前序遍历

  2. 429. N 叉树的层序遍历

  3. 590. N 叉树的后序遍历

Codefun2000

难度按序号递增,一次刷个够!

1.P1224 携程 2023.04.15-春招-第三题-魔法之树

2.P1159. 2022年清华大学(深圳)保研夏令营机试题-第一题-树上计数

3.P1065. 米哈游 2023.3.5-最长的通讯路径

4.P1196 华为 2023-04-19-第二题-塔子哥出城

5.P1044. 拼多多内推笔试-2023.2.22.投喂珍珠

6.P1193. 腾讯音乐 2023.04.13-暑期实习-第二题-价值二叉树

7.P1081. 百度 2023.3.13-第三题-树上同色连通块

更多请见:知识点分类-训练-深度优先搜索专栏

代码

CPP

#include <bits/stdc++.h>
using namespace std;
​
// 将字母映射到一个ID
int idx(char ch) {
    if (ch == 'R') return 0;
    else if (ch == 'G') return 1;
    return 2;
}
​
// 判断两个子树 A 和删掉了子树 A 的树中每个颜色是否都还存在
bool check(vector<int>& A, vector<int>& B) {
    for (int i = 0; i < 3; ++i) {
        if (A[i] == 0 || B[i] == A[i]) {
            return false;
        }
    }
    return true;
}
​
int main()
{
    int n;
    cin >> n;
​
    vector<vector<int>> g(n);
    for (int i = 2; i <= n; ++i) {
        int p; cin >> p;
        g[i - 1].emplace_back(p - 1);
        g[p - 1].emplace_back(i - 1);
    }
​
    string s;
    cin >> s;
​
    vector<vector<int>> cnt(n, vector<int>(3, 0));
​
    int ans = 0;
    // first = true 表示是在统计整个树的 RGB 
    // first = false 表示是在统计答案
    function<void(int,int,bool)> dfs = [&](int u, int fa, bool first) {
        for (int v: g[u]) {
            if (v == fa) continue;
            dfs(v, u, first);
            if (first) {
                // 累加子树中的所有 RGB
                for (int j = 0; j < 3; ++j) cnt[u][j] += cnt[v][j];
            } else {
                // 如果断掉 u-v 这条边,使得两棵树都有 RGB,则答案 + 1
                if (check(cnt[v], cnt[0])) ans += 1;
            }
        }
        if (first) cnt[u][idx(s[u])] += 1;
    };
​
    dfs(0, -1, true);
    dfs(0, -1, false);
​
    cout << ans << "\n";
​
    return 0;
}

python

# 将字母映射到一个ID
def idx(ch):
    if ch == 'R':
        return 0
    elif ch == 'G':
        return 1
    return 2
​
​
# 判断两个子树 A 和删掉了子树 A 的树中每个颜色是否都还存在
def check(A, B):
    for i in range(3):
        if A[i] == 0 or B[i] == A[i]:
            return False
    return True
​
​
n = int(input())
​
g = [[] for _ in range(n)]
p = list(map(int, input().split(" ")))
for i in range(2, n + 1):
    g[i - 1].append(p[i - 2] - 1)
    g[p[i - 2] - 1].append(i - 1)
​
s = input()
​
cnt = [[0] * 3 for _ in range(n)]
​
ans = 0
​
​
# first = true 表示是在统计整个树的 RGB 
# first = false 表示是在统计答案
def dfs(u, fa, first):
    global ans
    for v in g[u]:
        if v == fa:
            continue
        dfs(v, u, first)
        if first:
            # 累加子树中的所有 RGB
            for j in range(3):
                cnt[u][j] += cnt[v][j]
        else:
            # 如果断掉 u-v 这条边,使得两棵树都有 RGB,则答案 + 1
            if check(cnt[v], cnt[0]):
                ans += 1
    if first:
        cnt[u][idx(s[u])] += 1
​
​
dfs(0, -1, True)
dfs(0, -1, False)
​
print(ans)

Java

import java.util.*;
​
public class Main {
​
    static int ans;
​
    public static int idx(char ch) {
        if (ch == 'R') return 0;
        else if (ch == 'G') return 1;
        return 2;
    }
​
    public static boolean check(int[] A, int[] B) {
        for (int i = 0; i < 3; ++i) {
            if (A[i] == 0 || B[i] == A[i]) {
                return false;
            }
        }
        return true;
    }
​
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
​
        List<List<Integer>> g = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            g.add(new ArrayList<>());
        }
​
        for (int i = 2; i <= n; i++) {
            int p = sc.nextInt();
            g.get(i-1).add(p-1);
            g.get(p-1).add(i-1);
        }
​
        String s = sc.next();
​
        int[][] cnt = new int[n][3];
​
        // first = true 表示是在统计整个树的 RGB 
        // first = false 表示是在统计答案
        dfs(0, -1, true, g, s, cnt);
        ans = 0;
        dfs(0, -1, false, g, s, cnt);
​
        System.out.println(ans);
    }
​
    public static void dfs(int u, int fa, boolean first, List<List<Integer>> g, String s, int[][] cnt) {
        for (int v : g.get(u)) {
            if (v == fa) continue;
            dfs(v, u, first, g, s, cnt);
            if (first) {
                // 累加子树中的所有 RGB
                for (int j = 0; j < 3; ++j) cnt[u][j] += cnt[v][j];
            } else {
                // 如果断掉 u-v 这条边,使得两棵树都有 RGB,则答案 + 1
                if (check(cnt[v], cnt[0])) ans += 1;
            }
        }
        if (first) cnt[u][idx(s.charAt(u))] += 1;
    }
}

Go

package main
​
import (
    "fmt"
)
​
// 将字母映射到一个ID
func idx(ch byte) int {
    if ch == 'R' {
        return 0
    } else if ch == 'G' {
        return 1
    }
    return 2
}
​
// 判断两个子树 A 和删掉了子树 A 的树中每个颜色是否都还存在
func check(A []int, B []int) bool {
    for i := 0; i < 3; i++ {
        if A[i] == 0 || B[i] == A[i] {
            return false
        }
    }
    return true
}
​
func main() {
    var n int
    fmt.Scan(&n)
​
    g := make([][]int, n)
    for i := 2; i <= n; i++ {
        var p int
        fmt.Scan(&p)
        g[i-1] = append(g[i-1], p-1)
        g[p-1] = append(g[p-1], i-1)
    }
​
    var s string
    fmt.Scan(&s)
​
    cnt := make([][]int, n)
    for i := range cnt {
        cnt[i] = make([]int, 3)
    }
​
    ans := 0
    // first = true 表示是在统计整个树的 RGB
    // first = false 表示是在统计答案
    var dfs func(u, fa int, first bool)
    dfs = func(u, fa int, first bool) {
        for _, v := range g[u] {
            if v == fa {
                continue
            }
            dfs(v, u, first)
            if first {
                // 累加子树中的所有 RGB
                for j := 0; j < 3; j++ {
                    cnt[u][j] += cnt[v][j]
                }
            } else {
                // 如果断掉 u-v 这条边,使得两棵树都有 RGB,则答案 + 1
                if check(cnt[v], cnt[0]) {
                    ans += 1
                }
            }
        }
        if first {
            cnt[u][idx(s[u])] += 1
        }
    }
​
    dfs(0, -1, true)
    dfs(0, -1, false)
​
    fmt.Println(ans)
}

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 g = new Array(n).fill(0).map(() => []);
    p = lines[1].split(' ').map(x => parseInt(x));
    for (let i = 2; i <= n; i++) {
        g[i - 1].push(p[i - 2] - 1);
        g[p[i - 2] - 1].push(i - 1);
    }
    const s = lines[2].trim();
    const cnt = new Array(n).fill(0).map(() => new Array(3).fill(0));
    let ans = 0;
    // first = true 表示是在统计整个树的 RGB
    // first = false 表示是在统计答案
    const dfs = (u, fa, first) => {
        for (let i = 0; i < g[u].length; i++) {
            const v = g[u][i];
            if (v === fa) continue;
            dfs(v, u, first);
            if (first) {
                // 累加子树中的所有 RGB
                for (let j = 0; j < 3; j++) {
                    cnt[u][j] += cnt[v][j];
                }
            } else {
                // 如果断掉 u-v 这条边,使得两棵树都有 RGB,则答案 + 1
                if (check(cnt[v], cnt[0])) ans += 1;
            }
        }
        if (first) cnt[u][idx(s[u])] += 1;
    };
    dfs(0, -1, true);
    dfs(0, -1, false);
    console.log(ans);
});
​
// 将字母映射到一个ID
function idx(ch) {
    if (ch === 'R') return 0;
    else if (ch === 'G') return 1;
    return 2;
}
​
// 判断两个子树 A 和删掉了子树 A 的树中每个颜色是否都还存在
function check(A, B) {
    for (let i = 0; i < 3; i++) {
        if (A[i] === 0 || B[i] === A[i]) {
            return false;
        }
    }
    return true;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/655468.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Django 网页Web开发】24. 实战项目:moudleForm的文件上传应用到城市管理(17)(保姆级图文)

目录 用户上传文件存放media如何启用1. 在urls.py中进行配置&#xff1a;2. 在settings.py中进行配置&#xff1a;3. 能够通过media的url访问文件 moudleForm上传文件实现城市管理1. moudle.py2. url.py3. city.py4. city.html5. 文件上传小结6. 城市管理效果总结 欢迎关注 『D…

Vivado远程开发探索

平时主要用轻薄本办公&#xff0c;但是有时候又需要用Vivado做一些开发的工作&#xff0c;就感觉生产力不够。如果能在远程的高性能服务器上跑Vivado综合实现就好了。前段时间用ubuntu下安装的Vivado发现有一个Remote Host的设置。所以就准备折腾一下这个。 WSL WSL的安装看官…

chatgpt赋能python:Python怎么调成黑色背景?

Python怎么调成黑色背景&#xff1f; 随着人们对代码编辑器的要求越来越高&#xff0c;许多开发者都喜欢在黑色背景下编写代码。不仅仅是视觉审美方面考虑&#xff0c;黑色背景对眼睛的伤害也比浅色背景要小得多。本篇文章将介绍如何在Python中调整为黑色背景 介绍 默认情况…

[C++刷题之旅]反转链表

&#x1f338;心有所向&#xff0c;日复一日&#xff0c;必有精进 &#x1f338;专栏&#xff1a;C刷题之旅 &#x1f338;作者&#xff1a;早凉 目录 题目一&#xff1a;反转链表 【题目链接】 【题目描述】 【解题思路】 【代码实现】 进阶&#xff1a;链表中指定区间…

【异步】Futurn、FutureTask、CompletionService、CompletableFuture

1. Callable 在这篇文章中 【Thread】线程的基本概念及创建方式&#xff08;一&#xff09;&#xff0c;我们知道创建线程的几种方式。其中&#xff0c;有两个是通过接口来实现的&#xff1a;Runnable、Callable。它们的区别如下&#xff1a; Runnable 接口中的方法是没有返回…

代码审计——XXE详解

为方便您的阅读&#xff0c;可点击下方蓝色字体&#xff0c;进行跳转↓↓↓ 01 漏洞描述02 审计要点03 漏洞特征04 漏洞案例05 修复方案 01 漏洞描述 XXE&#xff08;XML External Entity Injection&#xff09;是一种针对XML终端实施的攻击&#xff0c;漏洞产生的根本原因就是…

chatgpt赋能python:Python怎么调整行距

Python怎么调整行距 在Python中&#xff0c;我们可以使用不同的方法来调整文本行距。 在这篇文章中&#xff0c;我们将讨论最常用的两种方法&#xff1a;使用文本编辑器和使用Python代码。 使用文本编辑器 许多文本编辑器都具有设置行距的选项。 这通常在“格式”或“段落”…

SpringBoot + Mybatis Plus 实现的瀑布内容管理系统、CMS建站系统

瀑布内容管理系统 瀑布内容管理系统&#xff0c;采用SpringBoot Apache Shiro Mybatis Plus Thymeleaf 实现的内容管理系统(附带权限管理)&#xff0c;是搭建博客、网站的不二之选。 项目介绍 PB-CMS&#xff0c;致力于开发最精简、实用的CMS管理系统&#xff0c;适合搭建…

chatgpt赋能python:Python如何访问手机:探索移动端SEO优化的新途径

Python如何访问手机&#xff1a;探索移动端SEO优化的新途径 随着移动互联网的快速发展&#xff0c;移动端成为了各大搜索引擎的竞争焦点。对于SEO优化工程师而言&#xff0c;探索移动端SEO优化的新途径显得尤为关键。而Python作为一种强大的编程语言&#xff0c;在移动端SEO优…

MM32F3273G8P火龙果开发板MindSDK开发教程21 - PWM的使用

MM32F3273G8P火龙果开发板MindSDK开发教程21 - PWM的使用 1、简述 开发版的LED灯连接PA1脚&#xff0c;而PA1可以映射TIM2_CH2&#xff0c;所以我们用通用定时器2的TIM2_CH2输出PWM到PA1脚&#xff0c;通过更改PWM的占空比&#xff0c;来改变LED的亮度。 2、LED灯的初始化…

读数据压缩入门笔记06_上下文转换

1. 压缩算法可归为两类 1.1. 统计压缩&#xff08;即VLC&#xff09; 1.2. 字典压缩&#xff08;如LZ78&#xff09; 1.3. 从不同的角度利用了给定数据流中存在的统计冗余信息 2. 上下文变换 2.1. contextual transform 2.2. 给定一组相邻的符号集&#xff0c;对它们进行…

代码审计——任意文件下载详解

为方便您的阅读&#xff0c;可点击下方蓝色字体&#xff0c;进行跳转↓↓↓ 01 漏洞描述02 审计要点03 漏洞特征04 漏洞案例05 修复方案 01 漏洞描述 网站可能提供文件查看或下载的功能&#xff0c;如果对用户查看或下载的文件不做限制&#xff0c;就能够查看或下载任意的文件&…

大数据相关概念了解

Hadoop生态及Hive、HBase、Impala、HDFS之间的关系 Hadoop生态(什么是 Hadoop) Apache Hadoop软件库是一个框架&#xff0c;允许使用简单的编程模型在计算机集群之间对大型数据集进行分布式处理。它旨在从单个服务器扩展到数千台计算机&#xff0c;每台计算机都提供本地计算和…

【雕爷学编程】Arduino动手做(112)---2.4G24L01无线模块

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

chatgpt赋能python:Python怎么调整黑色的SEO?

Python怎么调整黑色的SEO&#xff1f; 在当今互联网的大环境下&#xff0c;各种搜索引擎的存在具有巨大的价值&#xff0c;特别是Google&#xff0c;百度等常用搜索引擎的SEO排名对于企业、个人品牌的宣传有着极其重要的意义。但是&#xff0c;如果出现黑色SEO的情况&#xff…

Spark操作HBase的数据,实现列值的计算

本文将介绍如何使用Spark操作HBase的数据&#xff0c;实现列之间的计算&#xff0c;以特征值计算为例。特征值是指从原始数据中提取出来的具有代表性或判别性的数值&#xff0c;可以用于数据分析或机器学习等领域。本文将使用hbase-spark连接器&#xff0c;通过Spark RDD的方式…

深度解析:圣湘生物的数字化转型升级之路(附方案详情)

随着“互联网”医疗技术在医疗行业的应用不断深化&#xff0c;数字化正在加速推进IVD行业的创新。 当前&#xff0c;IVD企业应对机遇和挑战的核心是提升竞争力。 IVD企业基于企业资源&#xff0c;提升综合竞争力主要分【硬实力】和【软实力】。 一方面&#xff1a;需要企业不…

跟李沐学AI;Meta可能让其开源AI模型商业化,让开发者赚钱

&#x1f989; AI新闻 &#x1f680; Meta可能让其开源AI模型商业化&#xff0c;让开发者赚钱 摘要&#xff1a;Meta正考虑将其开源大语言模型&#xff08;LLM&#xff09;的下一个版本用于商业用途&#xff0c;这可以为聊天机器人等提供支持。此举可能会让更多开发者使用替代…

张量分解(Cp、Tuker、Block-Term)

张量 张量是向量或矩阵在维度空间上的高阶扩展。 一个 ( p , q ) (p,q) (p,q)型的张量 T T T被定义为一个多重线性映射。 T : V ∗ ⋯ V ∗ V ⋯ V ↦ R , T:V^* \times \dots \times V^* \times V \times \dots \times V \mapsto \R, T:V∗⋯V∗V⋯V↦R, 其中 V V V 是…

用GPT4写2023高考语文作文,新课标I卷,Ⅱ卷

文章目录 新课标Ⅰ卷新课标Ⅱ卷总结 每年的高考语文题目都会是热议的话题&#xff0c;今年同样也不例外。但是今年讨论的话题除了作文题目本身之外&#xff0c;对于chatgpt写出的作文会是什么样子的也​让广大网友同样期待 新课标Ⅰ卷 好的故事&#xff0c;可以帮我们更好地表达…