持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情
一、题目描述:
1129. 颜色交替的最短路径 - 力扣(LeetCode)
在一个有向图中,节点分别标记为 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
二、思路分析:
- 将边转化为有向图的形式
- 分别从红蓝边开始进行两次BFS,取其中的较短距离
- 对于某个节点,存在分别从红蓝两边进入的两种情况,即每个节点可沿红蓝边各访问一次,需要两个数组分别标记从红和蓝边进入节点的情况,且由于第一轮BFS就会存在至多两次进入同一个节点的情况,因此初始距离只能设为最大
三、AC 代码:
class Solution {
void bfs(vector<int> &ans,bool red,vector<vector<int>>& redMap,vector<vector<int>>& blueMap){
int len=1,thisLenNum=1;
//是否已考虑从红或蓝边进入某节点的两种需要分开判断
vector<bool> redvis(ans.size(),false),bluevis(ans.size(),false);
queue<int> que;
que.emplace(0);
while(!que.empty()){
while(thisLenNum--){
int i=que.front();
que.pop();
if(red){
for(auto &nextRed:redMap[i])
if(!redvis[nextRed]){
redvis[nextRed]=true;
que.emplace(nextRed);
ans[nextRed]=min(len,ans[nextRed]);
}
}
else{
for(auto &nextBlue:blueMap[i])
if(!bluevis[nextBlue]){
bluevis[nextBlue]=true;
que.emplace(nextBlue);
ans[nextBlue]=min(len,ans[nextBlue]);
}
}
}
red=!red;
thisLenNum=que.size();
++len;
}
}
public:
vector<int> shortestAlternatingPaths(int n, vector<vector<int>>& redEdges, vector<vector<int>>& blueEdges) {
//转化为有向图的形式
vector<vector<int>> redMap(n),blueMap(n);
for(int i=0;i<redEdges.size();++i)
redMap[redEdges[i][0]].emplace_back(redEdges[i][1]);
for(int i=0;i<blueEdges.size();++i)
blueMap[blueEdges[i][0]].emplace_back(blueEdges[i][1]);
vector<int> ans(n,INT_MAX);
ans[0]=0;
//第一次BFS从红边开始
bfs(ans,true,redMap,blueMap);
//第二次BFS从蓝边开始
bfs(ans,false,redMap,blueMap);
//将仍为INT_MAX的位置置为-1
for(auto &i:ans)
if(i==INT_MAX) i=-1;
return ans;
}
};