leetcode

Leetcode Solutions (0x6A73)
git clone https://git.pngu.org/leetcode
Log | Files | Refs | Submodules | README

num_ways_assign_edge_weight2.py (2394B)


# 3559. Number of Ways to Assign Edge Weights II

"""
there is an undirected tree with 'n' nodes labeled from 1 to 'n', rooted at
node 1. the tree is represented by a 2d integer array 'edges' of length 'n -
1', where 'edges[i] = [ui, vi]' indicates that there is an edge between nodes
'ui' and 'vi'. return an array 'answer' where 'answer[i]' is the number of
valid assignments for 'queries[i]'. since the answer may be very large, apply
modulo 10^9+7 to each 'answer[i]'.
"""


class Solution:
    def assignEdgeWeights(
        self, edges: List[List[int]], queries: List[List[int]]
    ) -> List[int]:
        n, mod = len(edges) + 1, 10**9 + 7
        adj = [[] for _ in range(n + 1)]
        for u, v in edges:
            adj[u].append(v)
            adj[v].append(u)
        depth = [0] * (n + 1)
        parent = [0] * (n + 1)
        vis = [0] * (n + 1)
        vis[1] = 1
        q = deque([1])
        while q:
            node = q.popleft()
            for neighbour in adj[node]:
                if not vis[neighbour]:
                    vis[neighbour] = 1
                    depth[neighbour] = depth[node] + 1
                    parent[neighbour] = node
                    q.append(neighbour)
        log = max(1, n.bit_length())
        up = [parent]
        for k in range(1, log):
            prev = up[-1]
            up.append([prev[prev[v]] for v in range(n + 1)])

        def lca(u, v):
            if depth[u] < depth[v]:
                u, v = v, u
            diff = depth[u] - depth[v]
            for k in range(log):
                if (diff >> k) & 1:
                    u = up[k][u]
            if u == v:
                return u
            for k in range(log - 1, -1, -1):
                if up[k][u] != up[k][v]:
                    u = up[k][u]
                    v = up[k][v]
            return up[0][u]

        pow2 = [1] * (n + 1)
        for i in range(1, n + 1):
            pow2[i] = pow2[i - 1] * 2 % mod
        ans = []
        for u, v in queries:
            k = depth[u] + depth[v] - 2 * depth[lca(u, v)]
            ans.append(pow2[k - 1] if k else 0)
        return ans


if __name__ == "__main__":
    obj = Solution()
    print(obj.assignEdgeWeights(edges=[[1, 2]], queries=[[1, 1], [1, 2]]))
    print(
        obj.assignEdgeWeights(
            edges=[[1, 2], [1, 3], [3, 4], [3, 5]], queries=[[1, 4], [3, 4], [2, 5]]
        )
    )