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。
示例 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]
代码
class Solution
{
public:
vector<int> shortestAlternatingPaths(int n, vector<vector<int>>& red_edges, vector<vector<int>>& blue_edges)
{
// 由于存在自环或者平行边,所以定义哈希表保存每个结点对应的多条边并初始化
unordered_map<int, vector<int>> redGraph;
unordered_map<int, vector<int>> blueGraph;
for(auto& red: red_edges) redGraph[red[0]].push_back(red[1]);
for(auto& blue: blue_edges) blueGraph[blue[0]].push_back(blue[1]);
// 由于存在环和平行边,用数组 visit[x][y][color]=true 代表从节点x到节点y的且颜色为color的边被访问过,防止重复访问
// 第三维[2]有两维,第0维代表红色是否访问,第1维代表蓝色是否访问
// 所有的点初始化为0代表为被访问过
int visit[100][100][2];
memset(visit,0,sizeof(visit));
// step用于记录当前的步长,即从节点0到各节点的步长,从0逐渐+1自增
// res代表节点 0 到节点 X 的最短路径的长度,初始化为最大值
int step = 0;
vector<int> res(n, INT_MAX);
// 定义队列进行BFS,并进行初始化,pair<int, int>的意思是 <当前节点, 路径上颜色>
// 队列初始化先进<0, 1>, 再进<0, 0>,即我们先访问蓝色,再访问红色。
queue<pair<int, int>> myQue;
myQue.push(make_pair(0, 1));
myQue.push(make_pair(0, 0));
while(!myQue.empty())
{
int size = myQue.size();
++step;
for(int i=0; i < size; i++)
{
// 队首元素出队列,得到其节点,以及颜色
int curNode = myQue.front().first;
int curColor = myQue.front().second;
myQue.pop();
//若当前已访问的为蓝色边,希望下一个节点的边是红色;反之亦然
if(curColor == 1)
{
// 遍历当前节点每一个相邻的节点,寻找相连的红色边
for(auto& nextNode: blueGraph[curNode])
{
// 如果 curNode 和 nextNode 相连的红色边未被访问过,访问并加入队列
// 同时需要更新两点之间的最短路径
if(visit[curNode][nextNode][0] == 0)
{
res[nextNode] = min(res[nextNode], step);
// make_pair<nextNode, 0> 的含义是标记当前访问的边为红色,下次应该访问蓝色的
myQue.push(make_pair(nextNode, 0));
visit[curNode][nextNode][0] = 1;
}
}
}
else if(curColor == 0)
{
// 遍历当前节点每一个相邻的节点,寻找相连的蓝色边
for(auto& nextNode: redGraph[curNode])
{
// 如果 curNode 和 nextNode 相连的蓝色边未被访问过,访问并加入队列
// 同时需要更新两点之间的最短路径
if(visit[curNode][nextNode][1] == 0)
{
res[nextNode] = min(res[nextNode], step);
// make_pair<nextNode, 1> 的含义是标记当前访问的边为蓝色,下次应该访问红色的
myQue.push(make_pair(nextNode, 1));
visit[curNode][nextNode][1] = 1;
}
}
}
}
}
// 根据题意,0 到自身的距离为0;在上述操作后,若 0 到其他节点距离仍为INT_MAX,说明不存在符合要求的路径,设置为-1;
res[0] = 0;
for(int i=0; i < n; i++) if(res[i] == INT_MAX) res[i] = -1;
return res;
}
};
作者:godwriter
链接:https://leetcode-cn.com/problems/shortest-path-with-alternating-colors/solution/czhi-nan-shen-mei-de-bfsshi-xian-fu-chao-xiang-xi-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。