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];
    }
}

Dijkstra算法是一种用于解决单源最短路径问题的算法,它可以求解各个节点到达源点的最短路径或权值。在Java中,可以通过以下步骤实现Dijkstra算法: 1. 创建一个图的表示,包括节点和边的信息。 2. 初始化距离数组,用于记录每个节点到源点的最短距离。 3. 创建一个优先队列,用于选择下一个要访问的节点。 4. 将源点添加到优先队列中,并将其距离设置为0。 5. 循环执行以下步骤,直到优先队列为空: - 从优先队列中取出距离最小的节点。 - 遍历该节点的所有邻居节点,更新它们的最短距离。 - 如果更新后的最短距离小于原来的距离,则将该节点添加到优先队列中。 6. 最终,距离数组中存储的就是每个节点到源点的最短距离。 以下是一个使用Java实现Dijkstra算法的示例代码[^1]: ```java import java.util.*; public class DijkstraAlgorithm { public static void dijkstra(int[][] graph, int source) { int n = graph.length; int[] distance = new int[n]; boolean[] visited = new boolean[n]; Arrays.fill(distance, Integer.MAX_VALUE); distance[source] = 0; PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.comparingInt(node -> distance[node])); pq.offer(source); while (!pq.isEmpty()) { int node = pq.poll(); visited[node] = true; for (int i = 0; i < n; i++) { if (graph[node][i] != 0 && !visited[i]) { int newDistance = distance[node] + graph[node][i]; if (newDistance < distance[i]) { distance[i] = newDistance; pq.offer(i); } } } } // 输出最短距离 for (int i = 0; i < n; i++) { System.out.println("Node " + i + ": " + distance[i]); } } public static void main(String[] args) { int[][] graph = { {0, 4, 0, 0, 0, 0, 0, 8, 0}, {4, 0, 8, 0, 0, 0, 0, 11, 0}, {0, 8, 0, 7, 0, 4, 0, 0, 2}, {0, 0, 7, 0, 9, 14, 0, 0, 0}, {0, 0, 0, 9, 0, 10, 0, 0, 0}, {0, 0, 4, 14, 10, 0, 2, 0, 0}, {0, 0, 0, 0, 0, 2, 0, 1, 6}, {8, 11, 0, 0, 0, 0, 1, 0, 7}, {0, 0, 2, 0, 0, 0, 6, 7, 0} }; dijkstra(graph, 0); } } ``` 这段代码实现了Dijkstra算法,通过传入一个邻接矩阵表示的图和源点的索引,计算出每个节点到源点的最短距离。在示例中,我们使用了一个9个节点的图,并输出了每个节点到源点的最短距离。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值