Day49 | 53. 寻宝 prim算法 与kruskal算法

news2024/12/23 5:02:40

语言

Java

53. 寻宝

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

题目

题目描述

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

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

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

输入描述

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

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

输出描述

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

思路(prim算法)

prim算法核心就是三步,我称为prim三部曲,大家一定要熟悉这三步,代码相对会好些很多:

第一步,选距离生成树最近节点
第二步,最近节点加入生成树
第三步,更新非生成树节点到生成树的距离(即更新minDist数组)

  1. 初始化:

    • 初始化邻接矩阵 grid 为大值(例如 10001),代表顶点间无限大的距离。
    • 初始化 minDist 数组同样为大值,该数组会存储每个顶点到正在构建的树的最短距离。
    • 初始化 isInTree 数组为 false,表示没有顶点在树中。
  2. 读取输入:

    • 读取顶点数 v 和边数 e
    • 读取每条边及其权重,并填充邻接矩阵 grid
  3. prim算法:

    • 使用贪婪策略选择下一个要添加到最小生成树中的顶点。
    • 遍历除了第一个顶点之外的所有顶点(因为开始时我们假设一个顶点已经在树中)。
    • 对于每次迭代:
      • 找出离当前树最近的顶点并将其加入树中。
      • 更新不在树中的其他顶点到树的最短距离。
  4. 结果计算:

    • 汇总从第二个顶点到最后一个顶点的最小距离,得到最小生成树的总权重。
  5. 输出:

    • 输出最小生成树的总权重。

代码

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int v = scanner.nextInt();
        int e = scanner.nextInt();

        // 初始化邻接矩阵,所有值初始化为一个大值,表示无穷大
        int[][] grid = new int[v + 1][v + 1];
        for (int i = 0; i <= v; i++) {
            Arrays.fill(grid[i], 10001);
        }

        // 读取边的信息并填充邻接矩阵
        for (int i = 0; i < e; i++) {
            int x = scanner.nextInt();
            int y = scanner.nextInt();
            int k = scanner.nextInt();
            grid[x][y] = k;
            grid[y][x] = k;
        }

        // 所有节点到最小生成树的最小距离
        int[] minDist = new int[v + 1];
        Arrays.fill(minDist, 10001);

        // 记录节点是否在树里
        boolean[] isInTree = new boolean[v + 1];

        // Prim算法主循环
        for (int i = 1; i < v; i++) {
            int cur = -1;
            int minVal = Integer.MAX_VALUE;

            // 选择距离生成树最近的节点
            for (int j = 1; j <= v; j++) {
                if (!isInTree[j] && minDist[j] < minVal) {
                    minVal = minDist[j];
                    cur = j;
                }
            }

            // 将最近的节点加入生成树
            isInTree[cur] = true;

            // 更新非生成树节点到生成树的距离
            for (int j = 1; j <= v; j++) {
                if (!isInTree[j] && grid[cur][j] < minDist[j]) {
                    minDist[j] = grid[cur][j];
                }
            }
        }

        // 统计结果
        int result = 0;
        for (int i = 2; i <= v; i++) {
            result += minDist[i];
        }
        System.out.println(result);
        scanner.close();
    }
}

易错点

处理边界条件

思路(kruskal算法)

  1. 定义 Edge 类:

    • Edge 类用于存储边的信息,包括两个端点和权重。
    • 这个类允许我们将边作为独立的对象处理。
  2. 并查集:

    • father 数组用于存储每个节点的父节点。
    • init() 方法初始化 father 数组,使每个节点成为自己的根。
    • find() 方法用于查找一个节点所属的根节点。
    • join() 方法用于合并两个节点到同一个集合中。
  3. 主函数:

    • 读取顶点数 v 和边数 e
    • 读取每条边的信息,并将其存储到 edges 列表中。
    • 将 edges 列表按照边的权重进行排序。
    • 初始化并查集。
    • 遍历排序后的边,对于每条边,如果这条边连接的两个顶点不在同一个集合中,则将这条边加入最小生成树,并合并这两个顶点所在的集合。
    • 计算最小生成树的总权重,并输出结果。

代码

import java.util.*;

class Edge {
    int l, r, val;

    Edge(int l, int r, int val) {
        this.l = l;
        this.r = r;
        this.val = val;
    }
}

public class Main {
    private static int n = 10001;
    private static int[] father = new int[n];

    // 并查集初始化
    public static void init() {
        for (int i = 0; i < n; i++) {
            father[i] = i;
        }
    }

    // 并查集的查找操作
    public static int find(int u) {
        if (u == father[u]) return u;
        return father[u] = find(father[u]);
    }

    // 并查集的加入集合
    public static void join(int u, int v) {
        u = find(u);
        v = find(v);
        if (u == v) return;
        father[v] = u;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int v = scanner.nextInt();
        int e = scanner.nextInt();
        List<Edge> edges = new ArrayList<>();
        int result_val = 0;

        for (int i = 0; i < e; i++) {
            int v1 = scanner.nextInt();
            int v2 = scanner.nextInt();
            int val = scanner.nextInt();
            edges.add(new Edge(v1, v2, val));
        }

        // 执行Kruskal算法
        edges.sort(Comparator.comparingInt(edge -> edge.val));

        // 并查集初始化
        init();

        // 从头开始遍历边
        for (Edge edge : edges) {
            int x = find(edge.l);
            int y = find(edge.r);

            if (x != y) {
                result_val += edge.val;
                join(x, y);
            }
        }
        System.out.println(result_val);
        scanner.close();
    }
}

易错点

保 find() 方法能正确地找到根节点,并且路径压缩。

在 join() 方法中确保合并的是不同的集合。

总结

这两种算法还需要好好看一看。

这是我对象发给我看的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2080835.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MATLAB学习笔记】绘图——自定义标记(Marker)形状,实现与MATLAB自带标记基本一致的功能(自适应缩放、自适应裁剪)

目录 前言自定义标记函数自定义标记函数的说明纵横比调整将图形大小按磅数设置平移标记点绘制标记点边界标记点不裁剪 拓展功能——标记点自适应绘图区的缩放绘图区缩放回调函数标记点大小自适应标记点裁剪自适应 示例基本绘图自定义标记函数的使用 总代码主函数自定义标记函数…

RKNPU2从入门到实践 --- 【4】RKNN 模型构建【使用pycharm一步一步搭建RKNN模型】

目录 前言 1.1 RKNN 初始化及对象释放 1.1.1 概念介绍 1.1.2 实际演示 1.2 RKNN 模型配置 1.2.1 概念介绍 1.2.2 实际演示 1.3 模型加载 1.3.1 概念介绍 1.3.1.1 Caffe模型加载接口 1.3.1.2 TensorFlow模型加载接口 1.3.1.3 TensorFlowLite 模型加载接口 1.3.…

debian12 - 修改SSH端口连接回包

文章目录 debian12 - 修改SSH端口连接回包概述笔记先猜猜回包是哪个程序回的去下载对应版本的openssh代码工程用telnet测试的效果todo 关于ssh状态为active(start)的原因END debian12 - 修改SSH端口连接回包 概述 和同学讨论问题。 他说&#xff0c;用telnet去连接SSH端口&am…

数据仓库系列10:如何处理维度表中的变化类型?

想象一下,你正在管理一个电商平台的数据仓库。突然,你发现一个重要客户的地址发生了变化。这个简单的变更可能会对你的分析产生巨大影响。如何确保你的数据仓库能够准确地反映这种变化,同时又不丢失历史信息?欢迎来到数据仓库中最具挑战性的问题之一:维度表变化的处理。 目录…

记录imbalanced_learn离线安装

1 离线安装需要3个文件&#xff1a; 文件位置&#xff1a; ‘D:\非常重要\imbalanced-learn’ 2 复制到这个路径&#xff0c;即可 ‘…/miniconda3/lib/python3.8/site-packages’

数据结构与算法——Java实现 1.初识算法 —— 二分查找

目录 一、线性查找 二、二分查找 基础版 问题1 —— 循环条件 问题2 —— ij/2有没有问题 问题3 —— 代码中都写成 < 有何好处 改动版 人生的意义就是要独自穿过悲喜 —— 24.8.27 需求:在有序数组A内&#xff0c;查找值 target&#xff0c;如果找到返回索引&#xff0c;如…

小鹏在这次发布会上有哪些黑科技呢?

在今晚举办的小鹏10年热爱之夜&小鹏MONA MO3上市发布会上&#xff0c;何小鹏宣布&#xff0c;小鹏自研图灵芯片已于8月23日流片成功。据介绍&#xff0c;小鹏图灵芯片是全球首颗同时应用在AI汽车、机器人、飞行汽车的AI芯片&#xff0c;为AI大模型定制。 该芯片采用40核心…

【STM32】时钟体系

一、时钟体系 为什么需要时钟&#xff1f; 时钟可以为系统提供精确的定时&#xff0c;比如时间显示&#xff0c;定时器&#xff0c;pwm… 为芯片各功能模块提供工作势能,使能各组管脚工作&#xff0c;如果不使能&#xff0c;管脚无法工作 同步数据传输 给单片机提供一个时…

RabbitMQ中的死信交换机?(RabbitMQ延迟队列有了解过吗)

延迟队列 延迟队列:进入队列的消息会被延迟消费的队列。 延迟队列死信交换机 TTL&#xff08;过期时间&#xff09; 延迟队列的使用场景:超时订单、限时优惠、定时发布 死信交换机 当一个队列中的消息满足下列情况之一时&#xff0c;可以成为死信(dead letter): 消费者使…

探讨Vision Pro的成本优化与设计改进之路

随着Apple Vision Pro的发布,这款革命性的头戴式显示设备凭借其创新技术和用户体验吸引了大量关注。然而,高昂的价格成为了一个不可忽视的问题,阻碍了它的普及。为了让更多消费者能够负担得起这款产品,Apple需要探索各种方法来降低成本而不牺牲用户体验。本文将总结一些关于…

医用双目放大镜行业分析:前五大厂商占有大约39.0%的市场份额

一、当前市场状况 1. 市场规模与增长趋势 - 目前医用双目放大镜市场呈现出稳定增长的态势。据报告显示&#xff0c;预计到 2030 年全球市场规模将达到 5.2 亿美元&#xff0c;年复合增长率为 7.8%&#xff0c;这表明该行业具有较大的发展潜力。 - 增长的动力主要来自医疗行业…

排序算法(冒泡、插入、选择、快排、归并)原理动画及Python、Java实现

排序算法&#xff08;冒泡、插入、选择、快排、归并&#xff09;原理动画及Python、Java实现 1 冒泡排序1.1 原理1.2 Python、Java实现 2 插入排序2.1 原理2.2 Python、Java实现 3 选择排序3.1 原理3.2 Python、Java实现 4 快速排序4.1 原理4.2 Python、Java实现 5 归并排序5.1…

【机器学习】独立成分分析的基本概念、应用领域、具体实例(含python代码)以及ICA和PCA的联系和区别

引言 独立成分分析&#xff08;Independent Component Analysis&#xff0c;简称ICA&#xff09;是一种统计方法&#xff0c;用于从多个观察到的混合信号中提取出原始的独立信号源 文章目录 引言一、独立成分分析1.1 定义1.2 独立成分分析的基本原理1.3 独立成分分析的步骤1.3.…

RASA使用长文记录以及一些bug整理

RASA 学习笔记整理 一 安装 在虚拟环境中安装&#xff0c;进入python3版本的环境 conda activate python3 ai04机器旧版本&#xff1a;rasa-nlu和rasa-core是分开安装的 最新版本&#xff1a;rasa 将二者做了合并 直接安装 pip3 install rasa 在安装到如下步骤时候会报…

读软件开发安全之道:概念、设计与实施11安全地编程

1. 安全地编程 1.1. 在一个完整的软件设计过程中&#xff0c;我们要在创建和审查时就将安全性放在心中&#xff0c;但这只是产品开发过程的开始&#xff0c;接下来是实现、测试、部署、运行、监控、维护&#xff0c;并最终在生命周期结束时将其淘汰 1.2. 开发人员不仅必须忠实…

Android Launcher启动过程

## Launcher的启动流程&#xff1a; 1.Zygote进程 –> SystemServer进程 –> startOtherService方法 –> ActivityManagerService的systemReady方法 –> startHomeActivityLocked方法 –> ActivityStackSupervisor的startHomeActivity方法 –> 执行Activity…

Java | Leetcode Java题解之第380题O(1)时间插入、删除和获取随机元素

题目&#xff1a; 题解&#xff1a; class RandomizedSet {List<Integer> nums;Map<Integer, Integer> indices;Random random;public RandomizedSet() {nums new ArrayList<Integer>();indices new HashMap<Integer, Integer>();random new Rando…

Java9模块化系统JPMS(Java Platform Module System)

引言 随着Java技术的发展&#xff0c;开发人员面临的挑战之一是如何有效地管理和组织大型项目的依赖关系。传统的类路径&#xff08;classpath&#xff09;方法虽然简单&#xff0c;但在大型项目中却难以管理&#xff0c;尤其是在面对复杂的依赖关系时。为了解决这些问题&…

Kafka入门:从零开始了解分布式流处理平台

什么是Kafka Apache Kafka是由LinkedIn公司开发&#xff0c;后来由Apache软件基金会维护的一个分布式、分区、多副本的基于ZooKeeper协调的分布式消息系统。Kafka不仅是一个消息队列&#xff0c;还是一个强大的流处理平台&#xff0c;它能够实时地处理大量数据&#xff0c;满足…

Springboot如何实现redis消息的订阅发布

1. 环境准备 确保你已经安装了 Redis 服务器&#xff0c;并且可以在本地或者远程访问它。如果你还没有安装 Redis&#xff0c;请先安装并启动 Redis 服务。 2. 创建 Spring Boot 项目 使用 Spring Initializr 或者其他 IDE 创建一个新的 Spring Boot 项目&#xff0c;并添加以下…