【最短路径--BFS】1129. 颜色交替的最短路径

题目描述

(中等)在一个有向图中,节点分别标记为 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。

示例:

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

解题思路

单源最短路径问题,第一想法就是广度优先与Dijkstra算法。考虑到无权图,选择实现起来相对容易的广度优先算法。
相较于经典的最短路径问题,本题的难点在于如何高效的判断结点的重复访问(下文以去重代称)。传统的BFS去重可以借助dis[]数组(例如,初始化为-1,不为-1时表示该结点已找到最短路)或visited[]数组。但本题考虑到颜色交替这一特性,可能存在以不同颜色“重复” 访问某一结点后,可以到达原本无法到达的“目标”结点。
因此,只需在维护访问记录时增加color属性,即红/蓝色的访问分开维护。红色记为 ‘0’,蓝色记为 ‘1’。 介绍完整体思路后,代码细节如下。

代码实现

class Solution {
public:
    vector<int> shortestAlternatingPaths(int n, vector<vector<int>>& redEdges, vector<vector<int>>& blueEdges) {
        //创建邻接链表,相当于索引,节省检索效率。
        vector<vector<pair<int,int>>> graph(n);
        for(auto edge : redEdges){
            graph[edge[0]].push_back({edge[1], 0});
        }
        for(auto edge : blueEdges){
            graph[edge[0]].push_back({edge[1], 1});
        }
        //初始化最短距离
        vector<int> dis(n, -1);
        //visited数组,第二维:下标0为红,1为蓝
        vector<vector<bool>> visited(n, vector<bool>(2));
        //0结点作为起点,拥有红蓝所有权限
        visited[0] = {true, true};
        //初始化最短距离
        int distance = 0;
        //起点的最短距离为0
        dis[0] = distance;
        //创建队列,起点入队,开始遍历graph
        queue<pair<int, int>> que;
        //[弧头(有向边起点),颜色(0--红, 1 -- 蓝, 2 -- all)]
        que.push({0, 2});
        while(!que.empty()){
            int size = que.size();
            //新的”一层“,距离 + 1
            distance++;
            while(size--){
                auto node = que.front();
                que.pop();
                //遍历以当前结点为起点的所有边
                for(auto edge : graph[node.first]){
                	//满足颜色交替 && 尚未以次颜色访问结点,边的终点入队
                    if(node.second != edge.second && !visited[edge.first][edge.second]){
                        //维护访问记录visited[当前边的终点(弧尾)][颜色]
                        visited[edge.first][edge.second] = true;
                        que.push({edge.first, edge.second});
                        //dis数组尚未修改过,即为首次访问,亦表示最短到达!
                        if(dis[edge.first] == -1) dis[edge.first] = distance;
                    }
                }
            }
        }
        //直到队列为空返回答案!
        return dis;
    }
};

运行结果:
运行结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值