You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

70 lines
2.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class_2023_04_4_week;
import java.util.ArrayList;
// 给你一个 n 个节点的无向无根树,节点编号从 0 到 n - 1
// 给你整数 n 和一个长度为 n - 1 的二维整数数组 edges
// 其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间有一条边。
// 再给你一个长度为 n 的数组 coins ,其中 coins[i] 可能为 0 也可能为 1
// 1 表示节点 i 处有一个金币。
// 一开始,你需要选择树中任意一个节点出发。你可以执行下述操作任意次:
// 收集距离当前节点距离为 2 以内的所有金币,或者 移动到树中一个相邻节点。
// 你需要收集树中所有的金币,并且回到出发节点,请你返回最少经过的边数。
// 如果你多次经过一条边,每一次经过都会给答案加一。
// 测试链接 : https://leetcode.cn/problems/collect-coins-in-a-tree/
public class Code06_CollectCoinsInTree {
public static int collectTheCoins(int[] coins, int[][] edges) {
int n = coins.length;
ArrayList<ArrayList<Integer>> graph = new ArrayList<>();
int[] inDegree = new int[n];
for (int i = 0; i < n; i++) {
graph.add(new ArrayList<>());
}
for (int[] edge : edges) {
// 8 - 13
graph.get(edge[0]).add(edge[1]);
graph.get(edge[1]).add(edge[0]);
inDegree[edge[0]]++;
inDegree[edge[1]]++;
}
int[] queue = new int[n];
int l = 0, r = 0;
for (int i = 0; i < n; ++i) {
if (inDegree[i] == 1 && coins[i] == 0) {
queue[r++] = i;
}
}
while (l < r) {
int cur = queue[l++];
for (int next : graph.get(cur)) {
if (--inDegree[next] == 1 && coins[next] == 0) {
queue[r++] = next;
}
}
}
for (int i = 0; i < n; ++i) {
if (inDegree[i] == 1 && coins[i] == 1) {
queue[r++] = i;
}
}
int[] rank = new int[n];
while (l < r) {
int cur = queue[l++];
for (int next : graph.get(cur)) {
if (--inDegree[next] == 1) {
rank[next] = rank[cur] + 1;
queue[r++] = next;
}
}
}
int ans = 0;
for (int[] edge : edges)
if (rank[edge[0]] >= 2 && rank[edge[1]] >= 2) {
ans += 2;
}
return ans;
}
}