leetcode

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

network_recovery_pathways.py (2645B)


# 3620. Network Recovery Pathways

from collections import deque

"""
you are given a directed acyclic graph of 'n' nodes numbered from 0 to 'n -
1'.this is represented by a 2d array 'edges' of length 'm', where 'edges[i] =
[ui, vi, costi]' indicates a one-way communication from node 'ui' to node
'vi' with a recovery of 'costi'. some nodes may be offline. you are given a
boolean array where 'online[i] = true' means node 'i' is online. a path from
to 0 to 'n - 1' is valid if all intermediate nodes on the path are online,
and the total recovery cost of all edges on the path does not exceed 'k'.
return the maximum path score among all valid paths. if no valid path exists,
return -1.
"""


class Solution:
    def findMaxPathScore(
        self, edges: List[List[int]], online: List[bool], k: int
    ) -> int:
        n = len(online)
        graph = [[] for _ in range(n)]
        indegree = [0] * n
        for u, v, w in edges:
            graph[u].append((v, w))
            indegree[v] += 1
        q = deque()
        for i in range(n):
            if indegree[i] == 0:
                q.append(i)
        topo = []
        while q:
            u = q.popleft()
            topo.append(u)
            for v, _ in graph[u]:
                indegree[v] -= 1
                if indegree[v] == 0:
                    q.append(v)

        def check(limit):
            big = 10**30
            dp = [big] * n
            dp[0] = 0
            for u in topo:
                if dp[u] == big:
                    continue
                if u != 0 and u != n - 1 and not online[u]:
                    continue
                for v, w in graph[u]:
                    if w < limit:
                        continue
                    if v != n - 1 and not online[v]:
                        continue
                    if dp[u] + w < dp[v]:
                        dp[v] = dp[u] + w
            return dp[-1] <= k

        left = 0
        right = 10**9
        ans = -1
        while left <= right:
            mid = (left + right) // 2
            if check(mid):
                ans = mid
                left = mid + 1
            else:
                right = mid - 1
        return ans


if __name__ == "__main__":
    obj = Solution()
    print(
        obj.findMaxPathScore(
            edges=[[0, 1, 5], [1, 3, 10], [0, 2, 3], [2, 3, 4]],
            online=[true, true, true, true],
            k=10,
        )
    )
    print(
        obj.findMaxPathScore(
            edges=[[0, 1, 7], [1, 4, 5], [0, 2, 6], [2, 3, 6], [3, 4, 2], [2, 4, 6]],
            online=[true, true, true, false, true],
            k=12,
        )
    )