📜  门| GATE-CS-2016(Set 2)|问题15(1)

📅  最后修改于: 2023-12-03 15:12:43.190000             🧑  作者: Mango

门| GATE-CS-2016(Set 2)|问题15

本题考查树的遍历和搜索算法。

题目描述

给定一棵有n个节点的树,树的每个节点都是红色或绿色的。你需要选择某个节点作为根节点,并将树上的所有节点分为两组:

  • red组:所有红色节点以及与至少一个红色节点相邻的所有绿色节点。
  • green组:所有剩余节点。

你可以通过调整根节点,使子树中red组的节点数最多。请注意:每个节点属于树上的严格一个子树。

具体来说,给定树的边和每个节点的颜色,计算一个根节点,使得分组后red组节点数最多,输出red组的节点数。

输入格式

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

第二行,一个长度为 n 的字符串 colors,描述每个节点的颜色。其中每个字符是 "R" 表示红色节点,或是 "G" 表示绿色节点。

接下来 n-1 行,每行两个整数 ij,表示有一条边连接节点 ij

输出格式

一个整数,表示选定的根节点的时候可以得到的最大值。

样例输入
3
RGG
1 2
1 3
样例输出
2
样例解释

我们可以选择节点 1 作为根节点。这样的话,红色节点和绿色节点分别位于两个子树内,而红色节点的集合大小为 2。

提示

数据范围

  • $1 \leq n \leq 10^4$
  • 输入保证为一棵有效树。
解题思路

本题需要选择一个根节点,将树划分为两个部分。可以考虑使用定义在节点上的 DFS,计算该节点下的红色节点数和绿色节点数;或是使用 DFS,从每个所选的根节点出发,计算其所有子树中的红色节点数,然后取最大值。

具体算法思路如下:

  1. 初始化两个变量:result 表示当前结果,visited 表示插过没有;
  2. 对于每个节点,进行 DFS 遍历,计算该节点的配套;同时遍历它的邻居,并对于没有通过的邻居进行遍历,重复该过程;
  3. 如果该节点所在的配对位置,红色节点数大于该节点的父母,则 result 为该节点;如果相等,则看该节点是否比 result 更深,则更新 result;同时,它的父母的配对数量被更新为元素求和;
  4. 输出 result
参考代码
from typing import List
from collections import defaultdict

class Solution:
    def dfs(self, visited: List[bool], colors: str, count: List[List[int]], node: int) -> None:
        visited[node] = True
        for nei in self.adj_list[node]:
            if not visited[nei]:
                self.dfs(visited, colors, count, nei)
                count[node][0] += count[nei][1]
                count[node][1] += count[nei][0]
        if colors[node] == 'R':
            count[node][0] += 1
        else:
            count[node][1] += 1

    def maxRed(self, n: int, colors: str, edges: List[List[int]]) -> int:
        self.adj_list = defaultdict(list)
        for i, j in edges:
            self.adj_list[i].append(j)
            self.adj_list[j].append(i)
        result = 0
        visited = [False] * n
        count = [[0, 0] for _ in range(n)]
        self.dfs(visited, colors, count, 0)
        for i in range(n):
            if count[i][0] > count[i][1] and count[i][0] > count[0][1]:
                result = max(result, count[i][1])
            elif count[i][0] == count[i][1] and i != 0:
                result = max(result, count[i][1])
        return result