统一Prim(最小生成树)和Dijkstra(单源最短路径)代码(Java)

两者都采用到了贪心的策略,并且两个算法都一直维护着一个数组dist (Dijkstra),lowCost(最小生成树)
其中:lowCost[i]表示:当前构建的生成树集合到顶点i的最低代价
dist [i]表示:当前节点k到各个顶点的最短路径

算法思路:
不断从不在当前最优集合中去寻找和当前最优集合的最小代价,通过当前选中的最优决策来不断更新维护该数组(dist,lowCost),直到所有顶点都被标记为止。

—直接上代码看

743. 网络延迟时间(最短路径算法)

//Dijkstra算法 :从 k 点出发,到其他点 x 的最短距离的最大值   【和Prim算法很像】
class Solution {
    public int networkDelayTime(int[][] times, int n, int k) {
        final int distance = Integer.MAX_VALUE>>1;
        //graph初始化,邻接矩阵存储
        int[][] graph = new int[n+1][n+1];
        for(int i=0;i<=n;i++){
            Arrays.fill(graph[i],distance);  //权值距离先置为无限大
        }
        for(int i=0;i<=n;i++){
            graph[i][i] = 0;     //自己到自己为0
        }
        //按题目已知初始化
        int len = times.length;
        for(int i=0;i<len;i++){
            int[] cur = times[i];
            //有向图
            graph[cur[0]][cur[1]] = cur[2];
        }
 	//----------初始化完成(graph邻接矩阵)--------------
        //起点为1开始
        //dist[i]:表示当前顶点k到各个顶点i的最短距离
        int[] dist = new int[n+1];
        boolean[] visited = new boolean[n+1];
        Arrays.fill(dist,distance);  //dist[i] :表示k->i的距离
        //从 kk 点出发,到其他点 xx 的最短距离的最大值
        dist[k] = 0;  //自己到自己为0
        for(int c=0;c<n;c++){
            //找dist最小的值
            int index = -1;
            int minVal = distance;
            for(int i=1;i<=n;i++){
            //从不在最优集合中去寻找和当前最优的数
                if(!visited[i]){
                    if(minVal>dist[i]){
                        index = i;
                        minVal = dist[i];
                    }
                }
            }
            if(index==-1){  //出度为0直接return -1;
                return -1;
            }
            //找到了最小的,对最小的graph这一行进行展开 【出度扫描】
            visited[index] = true;  //收入到最优路径长度中
            for(int j=1;j<=n;j++){
                //dist[index]+graph[index][j]:表示能通过该最短路径作为跳板来找到dist[j]的最短路径
                //不难看出只要是graph[index][j]不等于无穷大那么就一定存在值
                dist[j] = Math.min(dist[j],dist[index]+graph[index][j]);
            }
        }
        int res = -1;
        for(int i=1;i<=n;i++){
            res = Math.max(res,dist[i]);
        }
        return res;
    }
}

1584. 连接所有点的最小费用(最小生成树)

class Solution {
    public int minCostConnectPoints(int[][] points) {
        final int max = Integer.MAX_VALUE>>1;
        int size = points.length;  //size个顶点
        //顶点选取集合 (seelcted)
        boolean[] visited = new boolean[size];   //顶点从0开始
        //某一时刻
        //init
        int[][] g = new int[size][size];
        //lowCost[i]表示:当前构建的生成树集合到顶点i的最低代价
        int[] lowCost = new int[size];
        for(int i=0;i<size;i++){
            for(int j=0;j<size;j++){
                int dict = dict(points,i,j);
                //无向图
                g[i][j] = dict;
                g[j][i] = dict;
            }
        }

//----------初始化完成(g邻接矩阵)--------------
     //init 选中一个点进行寻找--------------------------------------
        for(int i=0;i<size;i++){
            lowCost[i] = g[0][i];
        }
        //将第一个节点(index=0)收入最小生成树中
        //表示加入到了最小生成树集合中
        visited[0] = true;
        int sum = 0;  //记录结果
        int count = 1;
        while(count<size){
            //找一个最低代价的顶点加入
            int min = max;
            int index = -1;
            //选择lowCost最小值
            for(int i=0;i<size;i++){
            //从不在最小生成树中去寻找最小代价的节点
                if(!visited[i] && min>lowCost[i]){   //没有被选择的
                    index = i;  //最低点的下标
                    min = lowCost[i];
                }
            }
            if(index==-1){
                return sum;  //不找了
            }
            sum += min;
            count++;
            //记为最小生成树的节点
            visited[index] = true;  
            //更新lowCost数组
            for(int i=0;i<size;i++){
                if(visited[i]){
                    continue;
                }
                //不需要g[index][i]+lowCost[index]
                //这里借助当前刚加入到生成树的这个顶点跳板来更新lowCost数组
                lowCost[i] = Math.min(lowCost[i],g[index][i]);
            }
        }
        return sum;
    }
    //自己到自己0
    private int dict(int[][] points,int i,int j){
        return Math.abs(points[i][0]-points[j][0]) + Math.abs(points[i][1]-points[j][1]);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

践行~渐远

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值