返回

深度剖析:882. 细分图中的可到达节点 : 常规最短路运用题

后端

在图论问题中,寻找从一个节点到另一个节点的最短路径是一个经典且重要的课题。LeetCode 882题“细分图中的可到达节点”正是这样一道题目,它要求我们在一个经过细分后的图中,从节点0出发,计算最多能到达多少个节点。本文将详细解析这一问题,并提供有效的解决方案。

题目解析

题目描述了一个无向图,其中包含n个节点和若干条边。每条边都有一个权重值。我们需要将图中的每条边细分k次,细分后的图将包含n + k*e个节点(其中e是原图中的边数)。目标是确定从节点0出发,在细分后的图中最多能到达多少个节点。

解决方案

1. 构造邻接表

首先,我们需要构造细分后图的邻接表。对于原图中的每条边(u, v, w),我们需要在细分后的图中创建k+1个新的节点,并将这些节点相互连接。每个新节点的权重为0。

def construct_adj_list(n: int, edges: List[List[int]], k: int) -> List[List[Tuple[int, int]]]:
    adj_list = [[] for _ in range(n + k * len(edges))]
    for u, v, w in edges:
        for i in range(k + 1):
            adj_list[u + i * len(edges)].append((v + i * len(edges), w))
            adj_list[v + i * len(edges)].append((u + i * len(edges), w))
    return adj_list

2. 使用广度优先搜索(BFS)

接下来,我们使用广度优先搜索算法从节点0开始探索细分后的图。我们需要维护一个距离数组dist,用于记录从节点0到每个节点的最短距离。初始时,所有节点的距离设为无穷大,节点0的距离设为0。

from collections import deque

def reachable_nodes(n: int, edges: List[List[int]], k: int) -> int:
    adj_list = construct_adj_list(n, edges, k)
    dist = [float('inf')] * (n + k * len(edges))
    dist[0] = 0
    queue = deque([0])
    
    while queue:
        u = queue.popleft()
        for v, w in adj_list[u]:
            if dist[v] > dist[u] + w:
                dist[v] = dist[u] + w
                queue.append(v)
    
    reachable = sum(1 for d in dist if d != float('inf'))
    return reachable

3. 复杂度分析

  • 时间复杂度:O((n + ke)log(n + ke)),其中n是节点数,e是边数,k是细分次数。广度优先搜索算法的时间复杂度为O(V + E),其中V是节点数,E是边数。由于细分后的图有n + ke个节点和ke条边,因此时间复杂度为O((n + ke)log(n + ke))。

  • 空间复杂度:O(n + ke),其中n是节点数,e是边数,k是细分次数。广度优先搜索算法的空间复杂度为O(V + E),其中V是节点数,E是边数。由于细分后的图有n + ke个节点和ke条边,因此空间复杂度为O(n + ke)。

总结

LeetCode 882题“细分图中的可到达节点”通过构造邻接表和使用广度优先搜索算法,能够有效地解决从节点0出发在细分后的图中最多能到达多少个节点的问题。算法的时间复杂度为O((n + ke)log(n + ke)),空间复杂度为O(n + ke)。

参考资料