代码随想录算法训练营第六十一天| 53. 寻宝 Prim 算法、53. 寻宝 Kruskal 算法

ChatUI vs Ant Design X 技术选型对比 维度ChatUI优势轻量级、易上手、完美兼容 Ant Design全能型框架、企业级扩展性、深度模型集成局限性功能单一、缺乏高级交互支持学习曲线陡峭、包体积较大最佳实践单独聊窗口集成整体智能助手系统开发通过对比可见,ChatUI 适合快速实现基础对话功能,而Ant Design X 更适合构建复杂的 AI 驱动应用。实际选择时需结合项目规模、团队技术栈和对交互复杂度的需求综合评估。 阅读详情

[KamaCoder] 53. 寻宝(第七期模拟笔试)

[KamaCoder] 53. 寻宝(第七期模拟笔试)文章解释

题目描述

在世界的某个区域,有一些分散的神秘岛屿,每个岛屿上都有一种珍稀的资源或者宝藏。国王打算在这些岛屿上建公路,方便运输。

不同岛屿之间,路途距离不同,国王希望你可以规划建公路的方案,如何可以以最短的总公路距离将 所有岛屿联通起来(注意:这是一个无向图)。 

给定一张地图,其中包括了所有的岛屿,以及它们之间的距离。以最小化公路建设长度,确保可以链接到所有岛屿。

输入描述

第一行包含两个整数V 和 E,V代表顶点数,E代表边数 。顶点编号是从1到V。例如:V=2,一个有两个顶点,分别是1和2。

接下来共有 E 行,每行三个整数 v1,v2 和 val,v1 和 v2 为边的起点和终点,val代表边的权值。

输出描述

输出联通所有岛屿的最小路径总距离

输入示例
7 11
1 2 1
1 3 1
1 5 2
2 6 1
2 4 2
2 3 2
3 4 1
4 5 1
5 6 2
5 7 1
6 7 1
输出示例

数据范围:

6

2 <= V <= 10000;
1 <= E <= 100000;
0 <= val <= 10000;

[KamaCoder] 53. 寻宝 Prim 算法(第七期模拟笔试)

自己看到题目的第一想法

    完全理解错了, 我以为是找到一条从节点 1 出发到节点 n , 路上要经过所有节点的路径最短的方案. 题目要求的是将所有城市连接在一起后, 要求建造的公路是的长度是最短的.

看完代码随想录之后的想法

    对于希望节点连接在一起后, 节点连线的权值总和是最小的. 有两种方案, 一种是 prim 算法, 一种是 kruskal 算法.

    对于 prim 算法, 就是从一个节点出发, 将该节点添加到最小生成树中, 同时更新与该节点相连的其他节点的距离. 因为节点默认是不和最小生成树相连的, 因此初始化时需要随意添加一个节点到最小生成树中, 该节点添加到进来后, 最小生成树就是该节点. 当有一个节点添加到最小生成树时, 与该节点相连的其他节点距离最小生成树的距离就是确定的了, 同时也不可能有其他更短的连接方式连接到该节点. 因此, 每次选择距离最小生成树最近的节点添加到最小生成树, 并更新完与该节点相邻的节点距离该生成树的距离后, 距离该最小生成树最近的节点也就知道了. 不停的往最小生成树中添加距离最近的节点, 直到添加 n - 1次后, 最小生成树将有 n 个节点, 所有节点就计算完成了.

import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

prim 算法
public class Main {
    private static int[][] nodes = null;
    private static int[] minDist = null;
    private static boolean[] isInTree = null;
    // 记录相连的边
    // private static int[] parents = null;
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int vertexCount = 0;
        while (scanner.hasNext()) {
            vertexCount = scanner.nextInt();
            int sideCount = scanner.nextInt();
            minDist = new int[vertexCount + 1];
            nodes = new int[vertexCount + 1][vertexCount + 1];
            // 记录相连的边
            // parents = new int[vertexCount + 1];
            isInTree = new boolean[vertexCount + 1];
            for (int i = 0; i <= vertexCount; i++) {
                minDist[i] = Integer.MAX_VALUE;
            }
            int fromNode;
            int toNode;
            int val;
            for (int i = 0; i < sideCount; i++) {
                fromNode = scanner.nextInt();
                toNode = scanner.nextInt();
                val = scanner.nextInt();
                nodes[fromNode][toNode] = val;
                nodes[toNode][fromNode] = val;
            }
        }
        minDist[1] = 0;
        for (int i = 0; i < vertexCount - 1; i++) {
            int minDistIndex = 0;
            for (int j = 1; j <= vertexCount; j++) {
                if (!isInTree[j] && minDist[j] < Integer.MAX_VALUE && minDist[j] < minDist[minDistIndex]) {
                    minDistIndex = j;
                }
            }
            isInTree[minDistIndex] = true;
            for (int j = 1; j <= vertexCount; j++) {
                if (nodes[minDistIndex][j] != 0 && !isInTree[j] && nodes[minDistIndex][j] < minDist[j]) {
                    minDist[j] = nodes[minDistIndex][j];
                    // 记录相连的边
                    // parents[j] = minDistIndex;
                }
            }
        }
        int result = 0;
        for (int i = 1; i < minDist.length; i++) {
            // 记录相连的边: 打印
            // System.out.println(parents[i] + " -> " + i);
            result += minDist[i];
        }
        System.out.println(result);
    }
}

自己实现过程中遇到哪些困难 

    1. 没想到只要添加 n - 1 个节点到最小生成树即可完成到所有节点最小路径的计算. 最开始采用的是记录一下最小生成树的节点数量, 当所有节点都添加到最小生成树后, 则停止.

    2. 没有使用 boolean[] isInTree 来判断节点是否计算过, 而是使用 List<Integer> 来计算, 导致性能耗时

    3. 最严重的是, 一开始完全理解错了 prim 算法的意图, 以为是想找到一条从节点 1 出发到 节点 n, 最短的路径. 实际上找的是连接所有节点后, 路劲最短的连接方式.

[KamaCoder] 53. 寻宝(第七期模拟笔试)

[KamaCoder] 53. 寻宝(第七期模拟笔试) 文章解释

题目描述

在世界的某个区域,有一些分散的神秘岛屿,每个岛屿上都有一种珍稀的资源或者宝藏。国王打算在这些岛屿上建公路,方便运输。

不同岛屿之间,路途距离不同,国王希望你可以规划建公路的方案,如何可以以最短的总公路距离将 所有岛屿联通起来(注意:这是一个无向图)。 

给定一张地图,其中包括了所有的岛屿,以及它们之间的距离。以最小化公路建设长度,确保可以链接到所有岛屿。

输入描述

第一行包含两个整数V 和 E,V代表顶点数,E代表边数 。顶点编号是从1到V。例如:V=2,一个有两个顶点,分别是1和2。

接下来共有 E 行,每行三个整数 v1,v2 和 val,v1 和 v2 为边的起点和终点,val代表边的权值。

输出描述

输出联通所有岛屿的最小路径总距离

输入示例
7 11
1 2 1
1 3 1
1 5 2
2 6 1
2 4 2
2 3 2
3 4 1
4 5 1
5 6 2
5 7 1
6 7 1
输出示例
6

数据范围:
2 <= V <= 10000;
1 <= E <= 100000;
0 <= val <= 10000;

[KamaCoder] 53. 寻宝 Kruskal 算法(第七期模拟笔试)

自己看到题目的第一想法

    无

看完代码随想录之后的想法

    感觉 prim 和 kruskal 都让我有一点点似懂非懂的感觉. 特别是 kruskal 算法, 每次挑选权重更小的边, 如果产生了环路, 说明当前节点已经相连, 不需要继续添加. 非常合理, 又非常得过于符合直觉... 让我产生了一种, 不知道自己是不是真的懂了的感觉... 一般就是真的没有完全懂. 头疼.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

// 
public class Main {
    // ====> 并查集部分 开始 <====
    private static int[] father = null;
    // ====> 并查集部分 结束 <====
    
    // ====> Kruskal 部分 开始 <====
    private static class Edge {
        int from;
        int to;
        int val;
    }
    private static List<Edge> edges = new ArrayList<>();
    // ====> Kruskal 部分 结束 <====
    
    // 记录相连的边
    // private static int[] parents = null;
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            init(scanner.nextInt());
            int sideCount = scanner.nextInt();

            // 记录相连的边
            // parents = new int[vertexCount + 1];
            for (int i = 0; i < sideCount; i++) {
                Edge edge = new Edge();
                edge.from = scanner.nextInt();
                edge.to = scanner.nextInt();
                edge.val = scanner.nextInt();
                edges.add(edge);
            }
        }
        Collections.sort(edges, new Comparator<Edge>() {
            @Override
            public int compare(Edge edge1, Edge edge2) {
                return edge1.val - edge2.val;
            }
        });
        int result = 0;
        for (Edge edge : edges) {
            if (isSame(edge.from, edge.to)) {
                continue;
            }
            join(edge.from, edge.to);
            result += edge.val;
        }
        System.out.println(result);
    }
    
    // ====> 并查集部分 开始 <====
    private static void init(int nodeCount) {
        father = new int[nodeCount + 1];
        for (int i = 0; i <= nodeCount; i++) {
            father[i] = i;
        }
    }
    
    private static boolean isSame(int u, int v) {
        return find(u) == find(v);
    }
    
    private static int find(int u) {
        if (u == father[u]) {
            return u;
        }
        return father[u] = find(father[u]);
    }
    
    private static void join(int u, int v) {
        u = find(u);
        v = find(v);
        if (u == v) {
            return;
        }
        father[v] = u;
    }
    // ====> 并查集部分 结束 <====
}

自己实现过程中遇到哪些困难 

    无, Kruskal 算法在测试用例里性能是高一些的, 取决于排序算法吧.

SillyTavern 酒馆在 Mac 和 Linux 上的部署教程(含启动器安装方法) SillyTavern 是一个支持多种大模型聊接口的本地前端项目,适用于 MacOS 和 Linux 系统。本文提供了两种部署方式:手动安装和使用 SillyTavern Launcher 安装器。手动安装需要先安装 Git 和 NodeJS,然后克隆项目源码并运行启动脚本。使用 Launcher 则更为简便,适合新手用户,能够自动安装依赖和配置环境。部署完成后,用户可以通过浏览器访问本地服务器,加载角色卡片并连接大模型 API,享受二次元角色扮演聊的乐趣。无论是开发者还是终端用户,都能轻松完成 Sil 阅读详情

相关推荐

VS2019编译配置Easy3D

VS2019编译配置Easy3D

dayuhaitang1的博客 2553

代码随想录训练营第42期 Day57打卡 - 图论Part7 - Prim算法Kruskal算法

Prim算法求解加权无向图的最小生成树

记得要努力变强 2831

【STM32 CubeMX】I2C中断方式与DMA方式

在STM32 CubeMX环境中,I2C(Inter-Integrated Circuit)通信协议的实现可以采用中断方式或DMA(Direct Memory Access)方式。中断方式通过触发中断来处理数据传输,而DMA方式则利用直接内存访问技术来实现数据传输,减轻了CPU的负担。在选择I2C通信方式时,开发者需要根据具体的应用需求和性能要求来选择合适的方式。STM32 CubeMX提供了图形化配置工具,使得配置I2C通信方式变得更加便捷。

m0_62599305的博客 7675

代码随想录训练营 Day57打卡 图论part07 53. 寻宝primkruskal算法

代码随想录训练营 Day57打卡 图论part07 53. 寻宝primkruskal算法

qq_42952637的博客 1892

代码随想录算法训练营第五十七 | 53. 寻宝-kruskal算法

排序后的边顺序为[(1,2) (4,5) (1,3) (2,6) (3,4) (6,7) (5,7) (1,5) (3,2) (2,4) (5,6)]选边(1,2),节点1 和 节点2 不在同一个集合,所以生成树可以添加边(1,2),并将 节点1,节点2 放在同一个集合。选边(1,3),节点1 和 节点3 不在同一个集合,生成树添加边(1,3),并将节点1,节点3 放到同一个集合。选边(2,6),节点2 和 节点6 不在同一个集合,生成树添加边(2,6),并将节点2,节点6 放到同一个集合。

懒羊羊在努力的博客 1157

代码随想录算法训练营第五十七 | 53. 寻宝-prim算法

如果是二维数组,来记录两个点链接,例如 parent[节点编号A][节点编号B] = 1 ,parent[节点编号B][节点编号A] = 1,来表示 节点A 与 节点B 相连,那就没有上面说的这个注意事项了,当然这么做的话,就是多开辟的内存空间。选取一个距离 最小生成树(节点1) 最近的非生成树里的节点,节点2,3,5 距离 最小生成树(节点1) 最近,选节点 2(其实选 节点3或者节点2都可以,距离一样的)加入最小生成树。parent[节点编号] = 节点编号, 这样就把一条边记录下来了。

懒羊羊在努力的博客 1275

代码随想录算法训练营Day49 | Prim算法Kruskal算法

minDist 数组记录了最小生成树的边,所以在更新 minDist 数组的时候,就更新 parent 数组来记录对应的边。Kruskalprim 的关键区别在于,prim维护的是节点的集合,而 Kruskal 维护的是边的集合。它按照边的权重从小到大的顺序,依次将边加入图中,只要这条边不会与已经选择的边形成环路,就将其纳入最小生成树。遍历这个新顶点的所有邻居,如果通过新顶点到某个邻居的距离,比该邻居之前记录的距离更短,就更新这个邻居的距离。此时,连接它和树的那条边,就正式成为了最小生成树的一条边。

2401_86818319的博客 1030

代码随想录算法训练营day57:图07:prim算法精讲;kruskal算法精讲

连通图 的 极小连通子图,含有全部n个顶点,n-1条边——添加上一条边,一定会构成环——不是唯一的——可以用DFS/BFS 生成那么就是 最小生成树算法的任务所在。

weixin_65180740的博客 1120

Studying-代码随想录训练营day57| prim算法精讲、kruskal算法精讲

prim算法精讲、kruskal算法精讲

yachihaoteng的博客 1504

代码随想录算法训练营第五十七 | prim算法 kruskal算法

文章链接题目链接:53.寻宝

decode12的博客 826

代码随想录算法训练营第五十七 | prim算法kruskal算法精讲 卡码网53.寻宝

根据minDist数组,选组距离生成树最近的节点加入生成树,那么minDist数组里记录的其实也是最小生成树的边的权值。最后我们就生成了一个最小生成树,绿色的边将所有节点链接到一起,并且保证权值是最小的,因为我们在更新minDist数组的时候,都是选距离最小生成树最近的点加入到树中。minDist数组用来记录每一个节点距离最小生成树的最近距离,来寻找距离最小生成树最近的节点,加入到最小生成树,刚开始还没有最小生成树,所以随便选一个节点加入就好。1、第一步:选距离生成树最近节点。1、用什么结构来记录。

m0_50413530的博客 575

代码随想录算法训练营第四十九 | 卡码网53. 寻宝(最小生成树之prim算法、最小生成树之kruskal算法

代码随想录算法训练营第四十九 | 卡码网53. 寻宝(最小生成树之prim算法、最小生成树之kruskal算法

dewi的博客 739

代码随想录算法训练营第 56 | 53. 寻宝Prim + Kruskal

可以用 HashMap 或一维数组 int[] parent。不能用一维数组 int[] parent,因为可能会出现如下情况:1 同时连 2 和 3,会被覆盖。由于 Kruskal 算法直接是针对边进行遍历的。这里直接用 List<int[]> 来保存边。遍历 n - 1 次,因为每次循环找到了一条边,只要找到 n - 1 条边即可。不能用 List<int[]>,因为会添加很多次,需要覆盖之前的添加。节点从 1 到 n。拓展:输出最小生成树的每条边。拓展:输出最小生成树的每条边。适合稠密图,点少边多。

Unstoppable22的博客 387

代码随想录】【算法训练营】【第63】 [卡码53]寻宝

思路及算法思维,指路。题目来自。day 63,周二,ding~

day day up 434

代码随想录算法训练营第六十一| 图论7—卡码网53. 寻宝

图论第七primkruskal算法,说实话都没看的很懂,有点抽象难理解,只能照着题解理解一下了。

yuhao__z的博客 564

代码随想录算法训练营第五十九|prim算法kruskal算法

Prim 算法用于寻找加权连通图的最小生成树(Minimum Spanning Tree,MST)。最小生成树是指连接图中所有顶点的最小权重的树。该算法从一个起始节点开始,不断选择与已加入生成树的节点集最近的节点,并将其加入生成树,直到所有节点都包含在生成树中。第一步:选距离生成树最近的非生成树节点第二步:最近节点(cur)加入生成树第三步:更新非生成树节点到生成树的距离(即更新minDist数组)

weixin_43903745的博客 1078

代码随想录算法训练营第57|卡码网 53. 寻宝 prim算法精讲和kruskal算法精讲

prim算法 是从节点的角度 采用贪心的策略 每次寻找距离 最小生成树最近的节点 并加入到最小生成树中。prim算法核心就是三步:1.第一步,选距离最小生成树最近节点2.第二步,最近节点加入生成树3.第三步,更新非生成树节点到生成树的距离(即更新minDist数组)其中:minDist数组 用来记录 每一个节点距离最小生成树的最近距离。

summersnowzgq的博客 518

代码随想录算法训练营Day63|最小生成树算法primkruskal、kama 53.寻宝

最小生成树(Minimum Spanning Tree,MST)算法是图论中的一个重要概念,它是指在加权无向图中,找到一个边的子集,构成一个树形结构,该子集包含图中所有的顶点,同时保证所有边的权值之和最小。这个构成的树就称为最小生成树。这两种算法能够有效地找到加权无向图的最小生成树,但它们在处理图的顶点和边的关系上有所不同。普里姆算法从顶点出发,而克鲁斯卡尔算法从边出发。

github_35852648的博客 2146

代码随想录算法训练营第五十七|KamaCoder53. 寻宝

prim算法思路:prim算法主要分为三步,第一步是选取距离生成树最近的节点,第二步是把这个节点加入到生成树当中,第三步是更新所有不在生成树的节点到生成树的距离。然后需要循环v-1次,这样就可以建立v-1条边,设置一个cur代表当前加入生成树的节点,minval表示当前加入生成树的节点距离生成树的最小距离,首先遍历所有节点,选取不在生成树里的,并且离生成树最近的节点,然后加入到生成树当中,之后更新所有节点离这个生成树的最接近的距离。然后是一些并查集的模板代码

Liverpool0519的博客 529

代码随想录算法训练营Day55 | 最小生成树的prim算法kruskal算法

代码随想录算法训练营Day55 | 最小生成树的prim算法kruskal算法

Harryline的博客 326

代码随想录算法训练营第六十三 | prim算法kruskal算法、复习

prim算法 是从节点的角度 采用贪心的策略 每次寻找距离 最小生成树最近的节点 并加入到最小生成树中。数组里的数值初始化为最大数,因为本题 节点距离不会超过 10000,所以初始化最大数为 10001就可以。本题是最小生成树的模板题,最小生成树可以使用 prim算法,也可以使用 kruskal算法计算出来。prim 算法是维护节点的集合,而 kruskal 是维护边的集合。判断首尾两个节点是否在同一个集合,需要用到。

Danny_8的博客 822

数据库连接算法详解:从基础概念到嵌套循环优化

2.重复键在归并连接中的处理:排序归并连接遇到相同键时,需要保存或回溯同一键对应的记录组,然后输出笛卡尔积。(2)外连接:即使一方没有数据,也保留该侧数据,用NULL填充。对S中的键计算哈希值;(3)连接基数:连接结果的行数可能远大于任意一张输入表。设外表有R个页面,内表S个页面,比较次数O(R+R*S)5.哈希连接的限制:最适用于等值连接,不直接适用于比较。(1)build阶段:对较小的关系R建立哈希表。(1)内连接:只保留两张表之中能够匹配的内容。若R有M行,S有N行,则比较次数为O(MN)

jiangxiaohanya的博客 236

微机原理习题库(51单片机)含答案.pdf

。。。

spring boot 实战,springboot实战项目,Java源码.zip

spring boot 实战,springboot实战项目,Java源码

上一篇: 代码随想录算法训练营第六十天| 108. 冗余连接、109. 冗余连接II
下一篇: 代码随想录算法训练营第五十八天| 117. 软件构建、47. 参加科学大会
dreamtang
博客等级 码龄19年 715粉丝 · 64原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值