Dijkstra 算法(Java)

例题:743. 网络延迟时间

有 n 个网络节点,标记为 1 到 n。

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

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



输入:times = [[2,1,1],[2,3,1],[3,4,1]], n = 4, k = 2
输出:2

 

// 邻接表
class Table{
    public int u;
    public List<Integer> v = new ArrayList<>();
    public List<Integer> w = new ArrayList<>();
    Table(int u){
        this.u = u;
    }
}

// 单个节点
class Node{
    public int u;
    public int dis;
    Node(int u, int dis){
        this.u = u;
        this.dis = dis;
    }
}

class Solution {
    Table [] tables; // 邻接表
    int [] dis; // 离起点的距离
    int [] vis; // 是否访问过
    int [] p; // 访问路径
    
    // 初始化
    public void init(int n){
        tables = new Table[n]; 
        dis = new int[n];
        vis = new int [n];
        p = new int[n];
        for(int i=0;i<n;i++){
            tables[i] = new Table(i);
        }
    }

    // dijkstra
    public void dij(int n, int k){
        PriorityQueue<Node> queue = new PriorityQueue<>(new Comparator<Node>()
        {
            @Override
            public int compare(Node a, Node b){
                return  a.dis - b.dis ;
            }
        }); // 优先队列选择最短的边
        for(int i=0;i<n;i++) dis[i] = Integer.MAX_VALUE; //设置初始距离
        dis[k] = 0;
        queue.offer(new Node(k, 0));
        int cnt = 0; // 统计松弛次数
        
        while(!queue.isEmpty()){
            Node node= queue.poll();
            int u = node.u;
            Table table = tables[u];
            

            if(vis[u]!=0) continue;
            vis[u] = 1;

            // 小优化
            cnt ++;
            if(cnt >= n) break;
            
            // 标记临近节点
            for(int i = 0;i< table.v.size() ;i++){
                int w = table.w.get(i);
                int v = table.v.get(i);


                if(dis[v] > dis[u] + w){
                    dis[v] = dis[u] + w;
                    p[v] = u;
                    queue.offer(new Node(v, dis[v]));
                }
            }
        }

    }

    public int networkDelayTime(int[][] times, int n, int k) {
        // 构造邻接表
        init(n+1); // 初始化数组
        for(int i = 0;i < times.length;i++) {
            tables[times[i][0]].v.add(times[i][1]);
            tables[times[i][0]].w.add(times[i][2]);
        }
        dij(n+1, k); // 调用dijkstra
        Arrays.sort(dis); // 最短路径排序
        return dis[n-1]==Integer.MAX_VALUE?-1:dis[n-1];
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值