leetcode-743. 网络延迟时间

743. 网络延迟时间

最短路径的几种算法。

1. dijkstra 朴素

2. dijkstra堆优化版本

3 .bellman-ford算法

4. spfa

5. 弗洛伊德多源

1.朴素dijkstra算法

        //迪杰斯特拉
        boolean[] st = new boolean[n+1];    //标记是否已经选入集合
        int[][] g = new int[n+1][n+1];      //邻接矩阵
        int[] dist = new int[n+1];          //单源距离
        Arrays.fill(dist,Integer.MAX_VALUE/2);
        dist[k]=0;
        //初始化图
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++){
                if (i==j)   g[i][j]=0;
                else g[i][j]=Integer.MAX_VALUE/2;
            }
        for (int[] time:times){
            g[time[0]][time[1]] = time[2];
        }
        //进行n次选点
        for (int i=1;i<=n;i++){
            //选出距离源点最近的未选入集合的点
            int minV = -1;
            for (int i1=1;i1<=n;i1++){
                if (!st[i1] && (minV==-1 || dist[minV]>dist[i1])){
                    minV=i1;
                }
            }
            st[minV] = true;    //该点加入选中集合
            //用该点更新到其他点的距离
            for (int i1=1;i1<=n;i1++){
                if (g[minV][i1] <Integer.MAX_VALUE/2 && g[minV][i1]+dist[minV] < dist[i1] )
                    dist[i1]=g[minV][i1]+dist[minV];
            }
        }
        int leastMax = -1;
        for (int i=1;i<=n;i++){
            leastMax=Math.max(leastMax,dist[i]);
        }
        return leastMax>=Integer.MAX_VALUE/2 ? -1:leastMax;

2.堆优化版dijkstra

 //堆优化版本迪杰斯特拉 ----》选最小节点时用堆选取

        boolean[] st = new boolean[n+1];    //标记是否已经选入集合
        int[][] g = new int[n+1][n+1];      //邻接矩阵
        int[] dist = new int[n+1];          //单源距离
        Arrays.fill(dist,Integer.MAX_VALUE/2);
        dist[k]=0;
        //初始化图
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++){
                if (i==j)   g[i][j]=0;
                else g[i][j]=Integer.MAX_VALUE/2;
            }
        for (int[] time:times){
            g[time[0]][time[1]] = time[2];
        }
        PriorityQueue<int[]> pq = new PriorityQueue<>((a,b)-> a[0]-b[0]);
        pq.add(new int[]{0,k});
        //进行n次选点
        while(!pq.isEmpty()) {
            //选出距离源点最近的未选入集合的点      --------这里采用堆
            int minV = pq.poll()[1];
            if (st[minV])    continue;
            st[minV] = true;    //该点加入选中集合
            //用该点更新到其他点的距离
            for (int i1=1;i1<=n;i1++){
                if (g[minV][i1] <Integer.MAX_VALUE/2 && g[minV][i1]+dist[minV] < dist[i1] ){
                    dist[i1]=g[minV][i1]+dist[minV];
                    pq.add(new int[]{dist[i1],i1});
                }
            }
        }
        int leastMax = -1;
        for (int i=1;i<=n;i++){
            leastMax=Math.max(leastMax,dist[i]);
        }
        return leastMax>=Integer.MAX_VALUE/2 ? -1:leastMax;

3. bellman-ford

      // ======================bellman-ford=========================
        //进行K次循环-》代表最多走k条边       ,然后每次更新最小距离,需要用到一个backup数组

        int[] dist = new int[n+1];          //单源距离
        int[] backup = new int[n+1];
        Arrays.fill(dist,Integer.MAX_VALUE/2);
        dist[k]=0;
        //不需要初始化图,直接对所有边遍历
        for(int i=0;i<times.length;i++){
            backup = Arrays.copyOf(dist,n+1);
            for(int[] time:times){
                int a = time[0],b=time[1],w=time[2];
                if (dist[b]>backup[a]+w)    dist[b]=backup[a]+w;
            }
        }
        int leastMax = -1;
        for (int i=1;i<=n;i++){
            leastMax=Math.max(leastMax,dist[i]);
        }
        return leastMax>=Integer.MAX_VALUE/2 ? -1:leastMax;

4.spfa

class Solution {
    public int networkDelayTime(int[][] times, int n, int k) {
        //===================  SPFA ==================
        //使用队列存储只更新了最小距离的点。只有这些点更小了别的点的距离才可能更小
        int[] dist = new int[n+1];          //单源距离
        boolean[] st = new boolean[n+1];    //标记是否在队列中
        int[][] g = new int[n+1][n+1];      //邻接矩阵
        Arrays.fill(dist,Integer.MAX_VALUE/2);
        dist[k]=0;

        Queue<Integer> queue = new ArrayDeque<>();
        queue.add(k);
        st[k] = true;

        //初始化图
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++){
                if (i==j)   g[i][j]=0;
                else g[i][j]=Integer.MAX_VALUE/2;
            }
        for (int[] time:times){
            g[time[0]][time[1]] = time[2];
        }

        while (!queue.isEmpty()){
            int ver = queue.poll();
            st[ver] = false;
            for (int i=1;i<=n;i++){
                if (g[ver][i]<Integer.MAX_VALUE/2 && dist[i]>dist[ver]+g[ver][i]){
                    if (!st[i]){
                        queue.add(i);
                        st[i]=true;
                    }
                    dist[i] = dist[ver]+g[ver][i];
                }
            }
        }

        int leastMax = -1;
        for (int i=1;i<=n;i++){
            leastMax=Math.max(leastMax,dist[i]);
        }
        return leastMax>=Integer.MAX_VALUE/2 ? -1:leastMax;
    }
}

5.多源:弗洛伊德

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Queue;

class Solution {
    public int networkDelayTime(int[][] times, int n, int k) {
        //弗洛伊德算法

        int[][] g = new int[n+1][n+1];      //邻接矩阵
        
        //初始化图
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++){
                if (i==j)   g[i][j]=0;
                else g[i][j]=Integer.MAX_VALUE/2;
            }
        for (int[] time:times){
            g[time[0]][time[1]] = time[2];
        }
        
        for (int k1=1;k1<=n;k1++){
            for (int i=1;i<=n;i++){
                for (int j=1;j<=n;j++)
                    g[i][j]=Math.min(g[i][j],g[i][k1]+g[k1][j]);
            }
        }
        
        int leastMax = -1;
        for (int i=1;i<=n;i++){
            leastMax=Math.max(leastMax,g[k][i]);
        }
        return leastMax>=Integer.MAX_VALUE/2 ? -1:leastMax;
    }
}

6. 写一个邻接表用spfa求解的方法:

import java.beans.IntrospectionException;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Queue;

class Solution {
    public static int N = 6010; //定义最大的边数

    int idx=0;
    int[] h ;   //对应节点数
    int[] e = new int[N];   //边对应的节点
    int[] ne = new int[N];  //下一条边的下标
    int[] w = new int[N];   //每条边对应的权重


    //添加一条a指向b权重为c的边
    public void add(int a, int b, int c){
        e[idx]=b; w[idx]=c; ne[idx]=h[a]; h[a]=idx++;
    }
    public int networkDelayTime(int[][] times, int n, int k) {
        h= new int[n+1];
        int[] dist = new int[n+1];
        Arrays.fill(h,-1);
        Arrays.fill(dist,Integer.MAX_VALUE/2);

        dist[k]=0;

        //建图
        for (int[] time:times){
            add(time[0],time[1],time[2]);
        }

        //SPFA
        Queue<Integer> queue = new ArrayDeque<>();
        boolean[] st = new boolean[n+1];
        queue.add(k);
        st[k]=true;
        while(!queue.isEmpty()){
            int ver = queue.poll();
            st[ver] = false;
            for (int i=h[ver];i!=-1;i=ne[i]){
                int verB = e[i];    //这才是过去的点,注意了!
                if (dist[verB]>dist[ver]+w[i]){
                    //只有不在队列内时,才需要加入队列中
                    if (!st[verB]){
                        st[verB]=true;
                        queue.add(verB);
                    }
                    dist[verB]=dist[ver]+w[i];
                }
            }
        }

        int leastMax = -1;
        for (int i=1;i<=n;i++){
            leastMax=Math.max(leastMax,dist[i]);
        }
        return leastMax>=Integer.MAX_VALUE/2 ? -1:leastMax;

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值