时间戳——树中的应用

简介

参考来源:Leetcode299周赛T4题解
时间戳:节点在dfs被遍历到的开始以及结束时间。
具体地讲,我们可以在 DFS 一棵树的过程中,维护一个全局的时间戳 clock,每访问一个新的节点,就将 clock +1。同时,记录进入节点 x 时的时间戳 in[x],和离开(递归结束)这个节点时的时间戳 out[x]。

作用

判断两个节点是否存在父子关系。
根据 DFS 的性质,当我们递归以 x 为根的子树时,设 y 是 x 的子孙节点,我们必须先递归完以 y 为根的子树,之后才能递归完以 x 为根的子树。

从时间戳上看,如果 y 是 x 的子孙节点,那么区间 [in[y],out[y]] 必然被区间 [in[x],out[x]] 所包含。

反之,如果区间 [in[y],out[y]] 被区间 [in[x],out[x]] 所包含,那么 y 必然是 x 的子孙节点(换句话说 x 是 y 的祖先节点)。因此我们可以通过

\[\textit{in}[x]<\textit{in}[y]\le\textit{out}[y]\le\textit{out}[x] \]

来判断 x 是否为 y 的祖先节点,由于 in[y]≤out[y] 恒成立,上式可以简化为

\[\textit{in}[x]<\textit{in}[y]\le\textit{out}[x] \]

复杂度分析

时间复杂度:O(n^2)
空间复杂度:O(n)

示例

Leetcode299周赛T4

from itertools import combinations
from math import inf
from typing import *
#DFS时间戳
class Solution:
    def minimumScore(self, nums: List[int], edges: List[List[int]]) -> int:
        n = len(nums)
        g = [[] for _ in range(n)]
        for x, y in edges:
            g[x].append(y)
            g[y].append(x)

        xor, in_, out, clock = [0] * n, [0] * n, [0] * n, 0
        def dfs(x: int, fa: int) -> None:
            nonlocal clock
            clock += 1
            in_[x] = clock
            xor[x] = nums[x]
            for y in g[x]:
                if y != fa:
                    dfs(y, x)
                    xor[x] ^= xor[y]
            out[x] = clock
        dfs(0, -1)
        ans = inf
        for i in range(2, n):
            for j in range(1, i):
                if in_[i] < in_[j] <= out[i]:  # i 是 j 的祖先节点
                    x, y, z = xor[j], xor[i] ^ xor[j], xor[0] ^ xor[i]
                elif in_[j] < in_[i] <= out[j]:  # j 是 i 的祖先节点
                    x, y, z = xor[i], xor[i] ^ xor[j], xor[0] ^ xor[j]
                else:  # 删除的两条边分别属于两颗不相交的子树
                    x, y, z = xor[i], xor[j], xor[0] ^ xor[i] ^ xor[j]
                ans = min(ans, max(x, y, z) - min(x, y, z))
                
                if ans == 0: return 0  # 提前退出
        return ans

s=Solution()
nums = [1,5,5,4,11]
edges = [[0,1],[1,2],[1,3],[3,4]]
z=s.minimumScore(nums,edges)
print(z)
posted @ 2022-06-27 15:16  岸南  阅读(42)  评论(0编辑  收藏  举报