zoukankan      html  css  js  c++  java
  • Dijkstra-leetcode 743.网络延迟时间

    743.网络延迟时间

    N 个网络节点,标记为 1N

    给定一个列表 times,表示信号经过有向边的传递时间。 times[i] = (u, v, w),其中 u 是源节点,v 是目标节点, w 是一个信号从源节点传递到目标节点的时间。

    现在,我们从某个节点 K 发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1

    示例:

    img

    输入:times = [[2,1,1],[2,3,1],[3,4,1]], N = 4, K = 2
    输出:2
    

    注意:

    1. N 的范围在 [1, 100] 之间。
    2. K 的范围在 [1, N] 之间。
    3. times 的长度在 [1, 6000] 之间。
    4. 所有的边 times[i] = (u, v, w) 都有 1 <= u, v <= N0 <= w <= 100

    思路:

    信号的传递走的是最短路径,题目要求所有节点都收到信号所需时间,就需要找到最后收到信号的节点。

    可以看作从节点K开始,到其他节点的所有最短路径中最长的那一条。

    找最短路径使用Dijkstra算法,找到从K开始到其他节点的最短路径,最后从这些最短路径中找出最长的一条返回即可


    class Solution {
        int INF = (int)Double.POSITIVE_INFINITY;    //INF表示无穷大
        public int networkDelayTime(int[][] times, int N, int K) {
            int[][] matrix = new int[N+1][N+1];	//表示题目节点与边信息的邻接矩阵
            int[] dis = new int[N+1];   //储存K到其他节点最短路径
            int[] book = new int[N+1];  //记录已经找到最短距离的节点
            for(int i=0;i<N+1;i++){
                for(int j=0;j<N+1;j++){
                    matrix[i][j] = INF;		//初始化邻接矩阵
                }
            }
            for(int i=0;i<times.length;i++){
                matrix[times[i][0]][times[i][1]] = times[i][2];	//通过题目所给信息初始化邻接矩阵
            }
            for(int i=1;i<N+1;i++){
                dis[i] = matrix[K][i];		//根据邻接矩阵为dis赋初值,表示从K能到达的节点的节点距离
            }
            book[K] = 1;    //初始节点置为1
            dis[K] = 0;		//K到K的距离为0
            for(int i=1;i<N+1;i++){
                int min = INF;	
                int u = -1;  //Q中最短结点
                for(int j=1;j<N+1;j++){ //找到从K出发能到达的最近的节点
                    if(book[j] == 0 && dis[j] < min ){
                        min = dis[j];
                        u = j;
                    }
                }
                if(u==-1){
                    continue;
                }
                book[u] = 1;    //将最短节点标记为已找到
                for(int k=1;k<N+1;k++){     //对U的所有出边进行松弛
                    if( matrix[u][k] < INF ){	//只有U能到达的节点才会进入循环
                        if(dis[k] > dis[u] + matrix[u][k]){	//如果通过U中转比K直接到新节点路径短
                            dis[k] =  dis[u] + matrix[u][k];	//修改最短距离
                        }
                    }
                }
            }
            int ans = -1;
            for(int i=1;i<N+1;i++){	//遍历dis,如果还有K到其他节点的距离为INF,表示不能到达,返回-1
                if(dis[i] == INF)	
                    return -1;
                ans = Math.max(ans,dis[i]);
            }
            return ans;	//返回到其他节点的最远距离
        }
    }
    

    堆优化版本

    class Solution {
        int INF = (int)Double.POSITIVE_INFINITY;    //无穷大
        public int networkDelayTime(int[][] times, int N, int K) {
            Queue<Node> queue = new PriorityQueue<>(new MyCompare());	//优先队列,类型为Node
            int[][] matrix = new int[N+1][N+1];	//邻接矩阵
            int[] dis = new int[N+1];   //储存起点K到其他节点最短距离
            int[] book = new int[N+1];  //记录已经找到最短距离的节点
            for(int i=0;i<N+1;i++){		//初始化
                dis[i] = INF;
                for(int j=0;j<N+1;j++){
                    matrix[i][j] = INF;
                }
            }
            for(int i=0;i<times.length;i++){
                matrix[times[i][0]][times[i][1]] = times[i][2];
            }
            dis[K] = 0;		    
            queue.add(new Node(K,0));	  //将起点入队   
            while( !queue.isEmpty() ){
                Node temp = queue.poll();	    //取出队列中距离起点最近的节点 u
                int u = temp.n;
                if( book[u] == 1 )		
                    continue;
                book[u] = 1;		//因为节点u已经是离起点最近的节点,所以标记为已找到最小路径
                for(int i=1;i<N+1;i++){		
                    if( book[i] == 0 && matrix[u][i] != INF){//遍历所有未找到最小路径的节点	
                        if(dis[i] > dis[u] + matrix[u][i]){	//判断是否能通过u进行松弛	
                            dis[i] = dis[u] + matrix[u][i];		
                            queue.add(new Node(i,dis[i]));		
                        }
                    }
                }
            }
            int ans = -1;
            for(int i=1;i<N+1;i++){		//处理结果
                if(dis[i] == INF)
                    return -1;
                ans = Math.max(ans,dis[i]);
            }
            return ans;
        }
    }
    
    class MyCompare implements Comparator<Node>{    //优先队列比较规则
    
        public int compare(Node n1,Node n2){
            if( n1.step > n2.step ){
                return 1;
            }else{
                return -1;
            }
        }
    
    }
    
    class Node{    //优先队列数据元素
        int n;    //节点编号
        int step;    //距离起点的距离
        public Node(int a,int b){
            n = a ;
            step = b;
        }
    }
    

    理论上堆优化的写法应该比朴素写法快一些,但是提交的时候反而慢一些....暂时不知道原因

  • 相关阅读:
    day 01
    day14
    day12
    day13
    day11
    day9
    day10
    day08
    day07
    day06
  • 原文地址:https://www.cnblogs.com/ELAIRS/p/12822333.html
Copyright © 2011-2022 走看看