1129. 颜色交替的最短路径

文章描述了一种在有向图中寻找红色和蓝色边交替出现的最短路径的方法,利用广度优先搜索算法,计算从节点0到其他节点的两种类型路径(最后一步为红色或蓝色)的最短长度,并返回最小值。如果不存在交替路径,则返回-1。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值