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

这篇博客介绍了如何利用广度优先搜索算法解决一类特殊的最短路径问题,即在有向图中寻找从节点0出发,红色边和蓝色边交替出现的最短路径。通过维护两个颜色的访问记录,有效地避免了重复路径,并在过程中更新最短距离。最终给出了C++代码实现,展示了如何找到满足条件的最短路径。

题目描述

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

运行结果:
运行结果

### 东华OJ 颜色交替 最短路径算法 解题思路 颜色交替最短路径问题通常涉及一个图,其中节点或边有不同的颜色限制。解题的核心在于如何结合颜色交替的约束条件与最短路径算法(如BFS、Dijkstra等)进行求解。以下是详细的解题思路: #### 1. 问题建模 将迷宫或图中的每个位置视为节点,并根据颜色交替的规则构建图。如果当前节点的颜色为红色,则只能移动到蓝色节点;反之亦然。这种约束可以通过扩展状态空间来实现。 - **状态定义**:除了记录当前位置外,还需要记录当前所处的颜色状态。例如,使用二元组 `(x, y, color)` 表示当前位于 `(x, y)` 且上一步经过的颜色为 `color`。 - **转移规则**:从当前状态 `(x, y, color)` 可以转移到与其相邻且颜色不同的节点 `(x', y', !color)`。 #### 2. 算法选择 由于需要寻找最短路径,可以优先考虑广度优先搜索(BFS)。BFS能够保证在无权图中找到最短路径[^1]。 - **初始化**:从起点 `(sx, sy, initial_color)` 开始,将其加入队列,并标记为已访问。 - **队列元素**:队列中的每个元素应包含当前节点的位置和颜色状态。 - **终止条件**:当队列中的某个状态到达目标节点时,停止搜索并返回路径长度。 #### 3. 实现细节 以下是一个基于BFS颜色交替最短路径算法的伪代码实现: ```python from collections import deque def shortest_alternating_path(grid, start, end): # 定义方向数组 (上、下、左、右) directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] rows, cols = len(grid), len(grid[0]) visited = [[[False for _ in range(2)] for _ in range(cols)] for _ in range(rows)] queue = deque() queue.append((start[0], start[1], grid[start[0]][start[1]], 0)) # 初始状态 (x, y, color, steps) visited[start[0]][start[1]][grid[start[0]][start[1]]] = True while queue: x, y, color, steps = queue.popleft() if (x, y) == end: return steps for dx, dy in directions: nx, ny = x + dx, y + dy if 0 <= nx < rows and 0 <= ny < cols and grid[nx][ny] != color: # 颜色交替检查 next_color = grid[nx][ny] if not visited[nx][ny][next_color]: visited[nx][ny][next_color] = True queue.append((nx, ny, next_color, steps + 1)) return -1 # 如果无法到达终点,返回 -1 ``` #### 4. 关键点分析 - **颜色交替约束**:通过在状态中引入颜色维度,确保每次移动都符合颜色交替的要求。 - **多源多目标**:如果问题涉及多个起点或终点,可以在初始化时将所有起点加入队列。 - **复杂度**:假设图中有 `n` 个节点,每个节点最多有 `m` 条边,则时间复杂度为 \(O(n \times m)\),空间复杂度为 \(O(n \times m)\)[^1]。 #### 5. 特殊情况处理 - 如果起点和终点颜色相同且之间没有其他节点满足颜色交替条件,则直接返回 `-1`。 - 如果图中存在孤立节点或不连通区域,需提前判断是否可达。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值