Leetcode1129. 颜色交替的最短路径(medium,BFS)

1. 题目描述

在一个有向图中,节点分别标记为 0, 1, ..., n-1。图中每条边为红色或者蓝色,且存在自环或平行边。

red_edges 中的每一个 [i, j] 对表示从节点 i 到节点 j 的红色有向边。类似地,blue_edges 中的每一个 [i, j] 对表示从节点 i 到节点 j 的蓝色有向边。

返回长度为 n 的数组 answer,其中 answer[X] 是从节点 0 到节点 X 的红色边和蓝色边交替出现的最短路径的长度。如果不存在这样的路径,那么 answer[x] = -1

示例 1:

输入:n = 3, red_edges = [[0,1],[1,2]], blue_edges = []
输出:[0,1,-1]

示例 2:

输入:n = 3, red_edges = [[0,1]], blue_edges = [[2,1]]
输出:[0,1,-1]

示例 3:

输入:n = 3, red_edges = [[1,0]], blue_edges = [[2,1]]
输出:[0,-1,-1]

示例 4:

输入:n = 3, red_edges = [[0,1]], blue_edges = [[1,2]]
输出:[0,1,2]

示例 5:

输入:n = 3, red_edges = [[0,1],[0,2]], blue_edges = [[1,0]]
输出:[0,1,1]

提示:

  • 1 <= n <= 100
  • red_edges.length <= 400
  • blue_edges.length <= 400
  • red_edges[i].length == blue_edges[i].length == 2
  • 0 <= red_edges[i][j], blue_edges[i][j] < n

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-path-with-alternating-colors
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题分析

        由于是求最短路径,第一感是广度优先搜索问题。只不过,在选择邻接节点时要考虑颜色交替的约束条件。

        题目描述中提到“还存在自环或平行边”的条件,后者是指在两个节点之间可以存在一条红边和一条蓝边。前者意味着什么?是不是意味着,比如说当沿着某条红边进入某个节点后,该节点出去的边也都是红色,所以直接出去不满足颜色交替的条件,但是该节点有一条蓝色自环边,所以可以先沿这条蓝色自环边绕一圈然后再从红色边出去?这样就意味着在一条路径上是可以重复访问一个节点的?换句话说,只需要关心路径上边的唯一性,不必关心节点是否有重复?这样的话,需要以(inEdgeColor, node)标记唯一性。处理流程如下:

  •         (None, 0)入队列q,并加入已访问集合visited
  •         while q is not empty:
  •                 从队列q中弹出(inEdgeColor, node)
  •                 if inEdgeColor is red:
  •                         在blue_edges中搜索前进的路
  •                 elif inEdgeColor is red:
  •                         在red_edges中搜索前进的路 
  •                 else: # 仅限于起点
  •                         在red_edges和blue_edges合集中搜索前进的路

                        

            在以下代码实现中,对于后面的if...elif...else做了一点优化,详细参见代码。    

3. 代码实现

from typing import List
from collections import deque

class Solution:
    def shortestAlternatingPaths(self, n: int, redEdges: List[List[int]], blueEdges: List[List[int]]) -> List[int]:
        # Assuming 0 for red, 1 for blue, None for neither 0 nor 1
        q       = deque([(None,0,0)])
        visited = set([None,0])
        dist    = n * [-1]
        while len(q)>0:
            inEdgeColor,node,layer = q.popleft()
            # if node not in dist:
            if dist[node] < 0:
                dist[node] = layer
            if inEdgeColor != 0:
                for edge in redEdges:
                    if node==edge[0]:
                        if (0,edge[1]) not in visited:
                            q.append((0,edge[1],layer+1))
                            visited.add((0,edge[1]))
                            
            if inEdgeColor != 1:
                for edge in blueEdges:
                    if node==edge[0]:
                        if (1,edge[1]) not in visited:
                            q.append((1,edge[1],layer+1))
                            visited.add((1,edge[1]))               

        return dist

if __name__ == "__main__":
    import time
    sln = Solution()
    
    n = 3
    red_edges = [[0,1],[1,2]]
    blue_edges = []
    print(sln.shortestAlternatingPaths(n, red_edges, blue_edges))
    
    n = 3
    red_edges = [[0,1]]
    blue_edges = [[2,1]]
    print(sln.shortestAlternatingPaths(n, red_edges, blue_edges))
    
    n = 3
    red_edges = [[1,0]]
    blue_edges = [[2,1]]
    print(sln.shortestAlternatingPaths(n, red_edges, blue_edges))
    
    n = 3
    red_edges = [[0,1]]
    blue_edges = [[1,2]]
    print(sln.shortestAlternatingPaths(n, red_edges, blue_edges))
    
    n = 3
    red_edges = [[0,1],[0,2]]
    blue_edges = [[1,0]]
    print(sln.shortestAlternatingPaths(n, red_edges, blue_edges))
    
    n = 5
    red_edges = [[0,1],[3,2],[1,0],[4,3],[2,4]]
    blue_edges = [[2,4],[2,2],[1,3]]
    print(sln.shortestAlternatingPaths(n, red_edges, blue_edges))

        执行用时:60 ms, 在所有 Python3 提交中击败了15.64%的用户

        内存消耗:15.2 MB, 在所有 Python3 提交中击败了44.55%的用户

        虽然性能拉胯了一点,不过基本一遍做出来了,还是比较满意的。

        回到主目录:笨牛慢耕的Leetcode每日一解题解笔记(动态更新。。。) 

猜你喜欢

转载自blog.csdn.net/chenxy_bwave/article/details/124224326