LC 2603. 收集树中金币

https://leetcode.cn/problems/collect-coins-in-a-tree/

稍微有点难想到,看了 题解 之后才明白。

最开始我的想法非常直接,就是枚举每个节点,去判断”如果以这个节点为根,至少需要move到哪些节点才行“。 但是这种算法的时间复杂度就是O(n^2).

我也考虑过是否可以做换根DP,我看讨论区里面也给出了这个解法,但是稍微有点难理解。

最后题解中给出的拓扑排序的算法算是看懂了。

之前没有怎么写过无向图的拓扑排序,判断条件是 `ind[x]=1`. 然后在这种情况下面,可能ind[x]会变为负数,考虑0,1节点相连的情况。

然后在第二次遍历的时候,我们依然可以说使用 `ind[x]=1` 判断条件。

class Solution:
    def collectTheCoins(self, coins: List[int], edges: List[List[int]]) -> int:
        n = len(edges) + 1
        adj = [[] for _ in range(n)]
        ind = [0] * n
        for x, y in edges:
            adj[x].append(y)
            adj[y].append(x)
            ind[x] += 1
            ind[y] += 1

        # remove leaf node coin = 0
        from collections import deque
        q = deque()
        for i in range(n):
            if ind[i] == 1 and coins[i] == 0:
                q.append(i)
        while q:
            x = q.popleft()
            for y in adj[x]:
                ind[y] -= 1
                if ind[y] == 1 and coins[y] == 0:
                    q.append(y)

        # walk from leaf node to mark depth.
        q = deque()
        depth = [0] * n
        for i in range(n):
            if ind[i] == 1 and coins[i]:
                q.append(i)
                depth[i] = 0

        while q:
            x = q.popleft()
            for y in adj[x]:
                ind[y] -= 1
                # won't lead to coins = 0 leaf.
                if ind[y] == 1:
                    depth[y] = depth[x] + 1
                    q.append(y)

        edge = len([x for x in range(n) if depth[x] >= 2]) - 1
        if edge < 0: return 0
        ans = 2 * edge
        return ans