一、真题描述
牛牛的糖果树
牛牛的朋友送了她一棵节点数为 n 的糖果树(1号点为根节点),树上的每个糖果都有一个颜色。
牛牛吃糖果有一个习惯,她每次都会吃掉一整个子树的糖果,她喜欢与众不同,所以每次吃之前她都会把出现次数最多的颜色的糖果扔掉(可能有多个出现次数最多的颜色,此时要全部扔掉),她可以选择任意一棵子树吃掉,但她只能吃一次,因此他想知道她一次能吃到的所有糖果的颜色的异或和最大是多少(如果吃到了多个颜色相同的糖果,也需要做多次异或),你能帮帮她吗?
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 256M,其他语言512M
输入输出描述:

示例1:
输入例子:4
1 2 3 41 2
2 3
2 4
输出例子:0
例子说明:四个节点颜色各不相同。吃掉任意子树都会在吃之前把所有糖果扔掉,因此结果为0。
示例2:
输入例子:
4 1 1 2 2 1 2 2 3 2 4输出例子:1
例子说明:
吃掉以节点3或节点4为根的子树都只有一个节点,结果都为0,以1为根节点时颜色为1和颜色为2的节点数量都为2,因此结果也为0。吃掉以2为根的子树时节点3和节点4颜色都为2被删除,结果为节点2的颜色1。
二、解题思路&答案
解题思路:
-
树的构建:
- 使用邻接表存储树的结构。
- 节点编号从
1到n,其中1是根节点。
-
DFS 遍历:
- 使用递归的方式对树进行深度优先遍历。
- 每个节点返回两个信息:
colorCount:该子树中每种颜色的出现次数(Map<Integer, Integer>)。totalXor:该子树中所有糖果颜色的异或和(未移除任何颜色)。
-
合并子树信息:
- 合并所有子节点的颜色统计,得到当前节点的完整颜色分布。
- 合并所有子节点的异或和,并加上当前节点的颜色。
-
计算最大异或和:
- 找出当前子树中出现次数最多的颜色集合。
- 对这些颜色进行处理:若出现次数为奇数次,则异或其颜色值。
- 从
totalXor中减去这些异或值,得到最终的异或和。 - 更新全局最大异或和。
代码实现:
java:
import java.util.*;
public class CandyTree {
static int[] color;
static List<List<Integer>> adj;
static int maxXor;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
color = new int[n + 1]; // 1-based indexing
// Read colors
for (int i = 1; i <= n; i++) {
color[i] = scanner.nextInt();
}
// Build adjacency list
adj = new ArrayList<>();
for (int i = 0; i <= n; i++) {
adj.add(new ArrayList<>());
}
for (int i = 0; i < n - 1; i++) {
int u = scanner.nextInt();
int v = scanner.nextInt();
adj.get(u).add(v);
adj.get(v).add(u);
}
maxXor = 0;
dfs(1, -1);
System.out.println(maxXor);
}
static class Result {
Map<Integer, Integer> colorCount;
int totalXor;
Result(Map<Integer, Integer> colorCount, int totalXor) {
this.colorCount = colorCount;
this.totalXor = totalXor;
}
}
static Result dfs(int node, int parent) {
Map<Integer, Integer> colorCount = new HashMap<>();
int totalXor = 0;
for (int neighbor : adj.get(node)) {
if (neighbor != parent) {
Result childRes = dfs(neighbor, node);
// Merge child's colorCount
for (Map.Entry<Integer, Integer> entry : childRes.colorCount.entrySet()) {
int c = entry.getKey();
int cnt = entry.getValue();
colorCount.put(c, colorCount.getOrDefault(c, 0) + cnt);
}
// Merge child's XOR
totalXor ^= childRes.totalXor;
}
}
// Add current node's color
int currentColor = color[node];
colorCount.put(currentColor, colorCount.getOrDefault(currentColor, 0) + 1);
totalXor ^= currentColor;
// Find maximum frequency
int maxCount = 0;
for (int cnt : colorCount.values()) {
if (cnt > maxCount) {
maxCount = cnt;
}
}
// Collect colors with max frequency
List<Integer> colorsToRemove = new ArrayList<>();
for (Map.Entry<Integer, Integer> entry : colorCount.entrySet()) {
if (entry.getValue() == maxCount) {
colorsToRemove.add(entry.getKey());
}
}
// Compute removeXor
int removeXor = 0;
for (int c : colorsToRemove) {
int cnt = colorCount.get(c);
if (cnt % 2 == 1) {
removeXor ^= c;
}
}
// Compute final XOR
int currentFinalXor = totalXor ^ removeXor;
if (currentFinalXor > maxXor) {
maxXor = currentFinalXor;
}
return new Result(colorCount, totalXor);
}
}
615

被折叠的 条评论
为什么被折叠?



