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]
解题思路:
0表示红色,1表示蓝色。对于某一节点 x,从节点 000 到节点 x 的红色边和蓝色边交替出现的路径有两种类型:
类型 0:路径最终到节点 x 的有向边为红色;
类型 1:路径最终到节点 x 的有向边为蓝色。
如果存在从节点 0 到节点 x 的类型 0 的颜色交替路径,并且从节点 x 到节点 y的有向边为蓝色,那么该路径加上该有向边组成了从节点 0到节点 y 的类型 1 的颜色交替路径。类似地,如果存在从节点 0到节点 x 的类型 1 的颜色交替路径,并且从节点 x 到节点 y 的有向边为红色,那么该路径加上该有向边组成了从节点 0 到节点 y 的类型 0 的颜色交替路径。
使用广度优先搜索获取从节点 0 到某一节点的两种类型的颜色交替最短路径的长度,广度优先搜索的队列元素由节点编号和节点路径类型组成,初始时节点 0 到节点 0 的两种类型的颜色交替最短路径的长度都是 0,将两个初始值入队。对于某一个队列元素,节点编号为 x,节点路径类型为 t,那么根据类型 t 选择颜色为 1−t 的相邻有向边,如果有向边的终点节点 y 对应类型 1−t没有被访问过,那么更新节点 y 的类型 1−t 的颜色交替最短路径的长度为节点 x 的类型 t 的颜色交替最短路径的长度加 1,并且将它入队。
从节点 0 到某一节点的颜色交替最短路径的长度为两种类型的颜色交替最短路径长度的最小值。
class Solution {
public int[] shortestAlternatingPaths(int n, int[][] redEdges, int[][] blueEdges) {
List<Integer>[][] next=new List[2][n];
for(int i=0;i<2;i++){
for(int j=0;j<n;j++){
next[i][j]=new ArrayList<Integer>();
}
}
//红边在第一行,蓝边在第二行ledge[0]表示始边,egde[1]表示终边
for(int[] edge:redEdges){
next[0][edge[0]].add(edge[1]);
}
for(int[] edge:blueEdges){
next[1][edge[0]].add(edge[1]);
}
int[][] dist=new int[2][n];//两种类型的颜色最短路径长度
for(int i=0;i<2;i++){
Arrays.fill(dist[i],Integer.MAX_VALUE);
}
Queue<int[]> queue=new ArrayDeque<int[]>();
//初始时节点 0 到节点 0 的两种类型的颜色交替最短路径的长度都是 0
dist[0][0]=0;
dist[1][0]=0;
queue.offer(new int[]{0,0});
queue.offer(new int[]{0,1});
while(!queue.isEmpty()){
int[]pair=queue.poll();
int x=pair[0],t=pair[1];
for(int y:next[1-t][x]){
if(dist[1-t][y]!=Integer.MAX_VALUE){//有向边的终点节点 y 对应类型 1−t没有被访问过
continue;
}
dist[1-t][y]=dist[t][x]+1;//节点 y 的类型 1−t 的颜色交替最短路径的长度为节点 x 的类型 t 的颜色交替最短路径的长度加 1
queue.offer(new int[]{y,1-t});
}
}
int[] answer=new int[n];
for(int i=0;i<n;i++){
answer[i]=Math.min(dist[0][i],dist[1][i]);//取两种类型中的最小路径
if(answer[i]==Integer.MAX_VALUE){//不存在题目要求的路径
answer[i]=-1;
}
}
return answer;
}
}