图论----最小生成树讲解与相关题解

news2024/9/28 19:17:35

目前已更新系列

当前--图论----最小生成树讲解与相关题解

滑动窗口系列算法总结与题解一

算法系列----并查集总结于相关题解

图论---dfs系列

差分与前缀和总结与对应题解(之前笔试真的很爱考)

数论---质数判断、质因子分解、质数筛(埃氏筛、
 

最小生成树

是什么、有什么用

最小生成树:在无向带权图中选择一些边,在保证连通性的情况下,边的总权值最小

最小生成树可能不止一颗,只要保证边的权值最小,那就是最小生成树

如果无向带权图有n个点那么最小生成树一定会有n-1条边

扩展:最小生成树一定是最小瓶颈树

解决该类问题最好用的方法时KrusKal算法

  • 不需要建图,只用使用并查集的思想将建立一个father数组表示当前节点是属于哪个集合
  • 然后将边按照权值进行排序,遍历排序后的边,尝试将边上的点进行合并
  • 遍历完之后如果能够合并的边数==n-1条说明找到了一条最小生成树,没有找到说明该图不连通

一般遇到题目将你求将n个点联通然后求联通之后的每条边的权值最小,

或者求最小瓶颈树,也就是让每个点联通,保证总体权值最小,求在最小瓶颈树上边的最大权值,

Kruskal算法(最常用)

思路
  • 1、把所有的边从小到大进行排序,从权值小的边开始考虑(可以使用最小堆,也可以调用sort进行排序)
  • 2、如果连接当前的边不会形成环,就选择当前的边
  • 3、如果当前的边会形成环,就不要当前的边
  • 4、考察完所有边之后,最小生成树就得到了(或者得到n-1条边之后)

模板

题目链接:【模板】最小生成树 - 洛谷

最小生成树主要是用来求将找出图中所有

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;
import java.util.PriorityQueue;

/**
 * @Author wangdongsheng
 * @Date 2024/8/19 00:18
 */
public class Main {
    //建图所用
    public static final int MAXN=5010;
    public static final int MAXM=2*MAXN;



    //并查集所用
    static int[] father=new int[MAXN];
    //kuraskal算法所用
    //0:from,1:to,2:weight
    static PriorityQueue<int[]> heap=new PriorityQueue<>((a,b)->a[2]-b[2]);
    //并查集所用
    private static void build(int n){
        for (int i = 0; i <=n; i++) {

            father[i]=i;
        }
    }
    public static int find(int x){
        if (father[x]!=x){
            father[x]=find(father[x]);
        }
        return father[x];
    }
    //这里合并返回是否是同一个集合是为了如果能合并说明不是环那么计算权制
    //如果是false那么可能出现环不能计算权制
    public static boolean union(int x,int y){
        int fx=find(x);
        int fy=find(y);
        if (fx!=fy){
            father[fx]=fy;
            return true;
        }
        return false;

    }
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StreamTokenizer in = new StreamTokenizer(br);
        in.nextToken();int n=(int) in.nval;
        in.nextToken();int m=(int) in.nval;
        build(n);
        for (int i = 0; i < m; i++) {
            in.nextToken();int u=(int) in.nval;
            in.nextToken();int v=(int) in.nval;
            in.nextToken();int w=(int) in.nval;
            //放入小根队中,将边进行排序
            heap.offer(new int[]{u,v,w});
        }
        int cnt=0;//记录小根队中弹出的边数用来判断是否有环
        int ans=0;
        while (!heap.isEmpty()){
            int[] poll = heap.poll();
            int u=poll[0];
            int v=poll[1];
            int w=poll[2];
            if (union(u,v)){
                cnt++;
                ans+=w;

            }

        }
        System.out.println(cnt==n-1?ans:"orz");
    }

}

下面是使用sort进行排序的模板

public class 最小生成树 {
    public static int MAXN=5001;
    public static int MAXM=200001;
    public static int[] father=new int[MAXN];
    public static int[][] eages=new int[MAXM][3];
    public static void build(int m){
        for (int i = 1; i <=m ; i++) {
            father[i]=i;
        }
    }
    public static int find(int a){
        if(a!=father[a]){
            father[a]=find(father[a]);
        }
        return father[a];
    }
    public static boolean union(int a,int b){
        int fa=find(a);
        int fb=find(b);
        if (fa!=fb){
            //如果两个点代表的集合不是同一个,合并
            father[fa]=fb;
            return true;
        }else {
            return false;
            //说明两个点在同一个集合中,则说明要这条边就会形成环,返回false
        }
    }

    public static void main(String[] args) {
        int n,m;
        Scanner scanner = new Scanner(System.in);
        n=scanner.nextInt();
        m=scanner.nextInt();
        for (int i = 0; i < m; i++) {
            eages[i][0] = scanner.nextInt();
            eages[i][1] =scanner.nextInt();
            eages[i][2]=scanner.nextInt();
        }
        int ans=0;
        int eageCount=0;//记录合并使用了几条边,用于判断是否联通

        //排序
        Arrays.sort(eages,(a,b)->a[2]-b[2]);//以权值进行排序

        //开始并查集
        //初始化father数组
        build(n);
        for (int[] eage : eages) {
            if (union(eage[0],eage[1])){
                //合并
                eageCount++;
                ans+=eage[2];//加上权值
            }
            //出现环就不要这条边
        }
        System.out.println(eageCount==n-1?ans:"orz");
    }
}

检查边长度限制的路径是否存在

题目描述

解析

这题主要是理解题目:题目的意思就是给你一个请求查询数组queries,然后queries[i][0]表示from,queries[i][1]表示to,queries[i][2]:表示权制,题目就是要找出有没有一条从from到to的路径,使得每一条表的权制不超过限制的权制,

class Solution {

    //这题要求的是,给定一个查询,查询,u,v,w表示u到v的每一条边必须要小于限制w
    //所以我们转化一下思维,我们通过最小生成树的思想,同样先合并最小权制的边,
    //然后,将边权制小于限制的进行合并,
    //最后查询的时候就直接判断是否在同一个集合中就好了
    //然后有几个查询我们就做几次最小生成树
    //然后优化一下,我们可以让查询的边安权制排序后进行找答案,
    //由于要排序,排序之后原来数组的顺序就改变了,
    //因此我们数组中还需要记录对应原始的下标,这样就能复用并查集了
    //这是个无向图
    public static int MAXN = 100010;
    public static final int MAXM = 2 * MAXN;
    public static int[] father = new int[MAXN];

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

    public static int find(int x) {
        if (father[x] != x) {
            father[x] = find(father[x]);
        }
        return father[x];
    }

    public static void union(int x, int y) {
        int fx = find(x);
        int fy = find(y);
        if (fx != fy) {
            father[fx] = fy;
        }
    }

    public static boolean isSame(int x, int y) {
        return find(x) == find(y);
    }

    public boolean[] distanceLimitedPathsExist(int n, int[][] edgeList, int[][] queries) {
        build(n);
        //拷贝查询数组,添加一个索引
        //0:索引,1:索引,2:v,3:w
        int[][] newQueries = new int[queries.length][4];
        for (int i = 0; i < queries.length; i++) {
            newQueries[i][0] = i;
            newQueries[i][1] = queries[i][0];
            newQueries[i][2] = queries[i][1];
            newQueries[i][3] = queries[i][2];
        }
        //
        // 将这个按照权制排序减少重复建立最小生成树
        Arrays.sort(newQueries, (a, b) -> a[3] - b[3]);
        //将给的边进行排序
        Arrays.sort(edgeList, (a, b) -> a[2] - b[2]);
        boolean[] ans = new boolean[queries.length];
        //注意i放在外层,因为我们已经对查询的权制进行了排序,那么建立的并查集就是可以复用的
        int i = 0;
        for (int[] query : newQueries) {
            int rw = query[3];
            int ru = query[1];
            int rv = query[2];
            int index = query[0];
            //并查集
            for (; i < edgeList.length && (edgeList[i][2] < rw); i++) {
                int u = edgeList[i][0];
                int v = edgeList[i][1];
                union(u, v);

            }
            if (isSame(ru, rv)) {
                ans[index] = true;
            }
        }
        return ans;

    }
}

繁忙的都市

题目链接:[SCOI2005] 繁忙的都市 - 洛谷

题目描述

解析

这题也是模板题直接套模板就好了

public class Main {

    public static int MAXN=310;
    private static int MAXM=2*8010;

    //这里直接试用最小堆进行排序算了,就不用再去存放边的信息,然后再对边进行排序了
    private static PriorityQueue<int[]> minHeap=new PriorityQueue<>((a,b)->a[2]-b[2]);

    //并查集所用
    //记录并查中有多少条边,每次合并一次,边数就+1
    static int cnt=0;
    private static int[] father=new int[MAXN];
    private static void build(int n){
        for (int i = 0; i <=n; i++) {
            father[i]=i;
        }
        cnt=0;
    }
    private static int find(int x){
        if (father[x]!=x){
            father[x]=find(father[x]);
        }
        return father[x];
    }
    private static void union(int x,int y){
        int fx=find(x);
        int fy=find(y);
        if (fx!=fy){
            father[fx]=fy;
            cnt++;
        }
    }
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StreamTokenizer in = new StreamTokenizer(br);
        in.nextToken();int n=(int)in.nval;
        in.nextToken();int m=(int)in.nval;
        build(n);
        for (int i = 0; i < m; i++) {
            in.nextToken();int u=(int)in.nval;
            in.nextToken();int v=(int)in.nval;
            in.nextToken();int w=(int)in.nval;
            minHeap.offer(new int[]{u,v,w});
//            minHeap.offer(new int[]{v,u,w});
        }

        //Kruskal
        int max=0;

        while (!minHeap.isEmpty()){
            int[] poll = minHeap.poll();
            max=poll[2];
            union(poll[0],poll[1]);
            if (cnt==n-1) break;
        }
        System.out.println(cnt+" "+max);
    }
}

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

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

相关文章

信息学奥赛初赛天天练-79-NOIP2015普及组-基础题4-即时通讯软件、二叉树遍历、前序遍历、中序遍历、后序遍历、算法时间复杂度

NOIP 2015 普及组 基础题4 11 下面哪种软件不属于即时通信软件( ) A QQ B MSN C 微信 D P2P 16 前序遍历序列与中序遍历序列相同的二叉树为( ) A 根结点无左子树 B 根结点无右子树 C 只有根结点的二叉树或非叶子结点只有左子树的二叉树 D 只有根结点的二叉树或非叶子结点只有…

如何使用IDEA远程访问家里或者公司中无公网IP的内网MySQL数据库

文章目录 前言1. 本地连接测试2. Windows安装Cpolar3. 配置Mysql公网地址4. IDEA远程连接Mysql5. 固定连接公网地址6. 固定地址连接测试 前言 本教程主要介绍如何使用Cpolar内网穿透工具实现在IDEA中也可以远程访问家里或者公司的数据库&#xff0c;提高开发效率&#xff01;无…

在 Debian 上安装 IntelliJ IDEA 笔记(含 JDK 的安装)

在 Debian&#x1f4a9; 上安装 IntelliJ IDEA &#x1f4a1; 笔记&#xff08;含 JDK 的安装&#xff09; 下载安装 JDKJDK17JDK8 安装 IntelliJ IDEA Community添加桌面启动项&#xff08;快捷方式&#xff09; 参考资料 下载 两个包已经下好了&#xff0c;一个JDK17&#x…

OZON新品藏品,OZON收藏品推荐

OZON新品藏品&#xff0c;OZON收藏品推荐Top1 火车模型 Наши поезда №17 - Пассажирский электровоз ЧС2 商品id&#xff1a;1643982093 月销量&#xff1a;266 OZON新品藏品地&#xff1a;m6z.cn/5H6fQR&#xff08;浏览器复制打开&a…

<数据集>车牌识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;2000张 标注数量(xml文件个数)&#xff1a;2000 标注数量(txt文件个数)&#xff1a;2000 标注类别数&#xff1a;1 标注类别名称&#xff1a;[License] 序号类别名称图片数框数1License20002965 使用标注工具&am…

嵌入式单片机开发学习路线,从入门到高薪就业,保姆级学习攻略!

嵌入式就业方向及具体细分岗位如下&#xff1a; 方向 岗位 单片机开发 单片机开发工程师&#xff08;MCU开发工程师&#xff09; RTOS开发工程师 Linux应用开发 Linux应用工程师 QT开发工程师 Linux多媒体开发工程师 Linux驱动开发 Linux/Android驱动开发工程师 Linux设…

【建议收藏】100个Python精选库

Python为啥这么火&#xff0c;这么多人学&#xff0c;就是因为简单好学&#xff0c;功能强大&#xff0c;整个社区非常活跃&#xff0c;资料很多。而且这语言涉及了方方面面&#xff0c;比如自动化测试&#xff0c;运维&#xff0c;爬虫&#xff0c;数据分析&#xff0c;机器学…

鸿蒙(API 12 Beta3版)【识别图像数据】

基本概念 图像数据识码能力支持对相机预览流数据中的码图进行扫描识别&#xff0c;并获取信息。 场景介绍 图像数据识码能力支持对相机预览流数据中的条形码、二维码、MULTIFUNCTIONAL CODE进行识别&#xff0c;并获得码类型、码值、码位置信息和相机变焦比。该能力可用于一…

马斯克被告“狗狗币传销”!索赔2580亿美元,法官驳回诉讼!马斯克与狗狗币的不解之缘!

在数字货币领域&#xff0c;每一次波动都牵动着全球投资者的神经&#xff0c;而埃隆马斯克&#xff08;Elon Musk&#xff09;——这位科技界的传奇人物&#xff0c;更是以其独特的言行不断在加密货币市场上掀起波澜。近期&#xff0c;关于马斯克与狗狗币&#xff08;Dogecoin&…

【C++STL详解(十三)】unordered系列容器的介绍与使用

目录 前言 一、unordered_map 介绍 使用 构造方式 修改 容量 迭代器 元素访问 查询 桶操作 二、unordered_set 介绍 使用 构造 修改 容量 迭代器&#xff08;只有单向) 查询 桶操作 三、unordered系列的性能测试 前言 前面提到的map/set是C98提供的关联…

使用手机挖掘IDOR漏洞赚取1500美元赏金

在今天的文章中&#xff0c;笔者将分享如何在手机上发现两个不安全的直接对象引用 (IDOR) 实例&#xff0c;并因此获得 1500 美元的赏金。 信息收集&#xff1a;了解目标 首先&#xff0c;我通常使用 Google dork&#xff08;谷歌语法&#xff1a;如“site:target.com about”…

斯坦福UE4 C++课学习补充24:伤害数值

创建并调用数值显示UI 显示数值用UMG实现。创建名为DamagePopup_Widget控件蓝图&#xff0c;添加一个数值文本框。设置如下&#xff0c;设置文本框为Is Variable 将场景投射到屏幕Project World Location to Widget Position节点&#xff1a;它的作用是在UE中将一个世界空间中…

智能新未来:2024世界机器人大会全景解析

8月21日至25日&#xff0c;2024世界机器人大会在北京北人亦创国际会展中心盛大举行。本次大会以“共育新质生产力 共享智能新未来”为主题&#xff0c;汇聚了全球近170家机器人企业&#xff0c;展示了超过600款创新产品&#xff0c;其中首发新品达60余款&#xff0c;人形机器人…

晚宴扫码查询座位号

在晚宴活动中&#xff0c;快速准确地查询座位号是提升参与者体验的关键。以下是通过扫码查询系统实现座位号查询的详细步骤。 步骤一&#xff1a;电脑端上传查询信息 1. 访问云分组官网。 2. 使用微信扫码登录系统。 3. 点击菜单“我的查询”。 步骤二&#xff1a;准备查询信…

文心快码帮你解大厂面试题:如何使用shell找到access log,如何找到访问量最多的url?

&#x1f381;&#x1f449;点击进入文心快码 Baidu Comate 官网&#xff0c;体验智能编码之旅&#xff0c;还有超多福利&#xff01;&#x1f381; 【大厂面试真题】系列&#xff0c;带你攻克大厂面试真题&#xff0c;秒变offer收割机&#xff01; ❓今日问题&#xff1a;在8…

Java框架spring(二)

一、AOP面向切面编程 1、AOP的概念 AOP&#xff08;AspectOrientedProgramming&#xff09;&#xff0c;意为&#xff1a;面向切面编程&#xff0c;通过 预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。 AOP是OOP的延续&#xff0c;是软件开发中的一个热点&…

URP custompasscustom render objects 下

上文 https://blog.csdn.net/qq_35158695/article/details/141708043?spm1001.2014.3001.5501 上次说了绘制流程&#xff0c;还需要指定FBO 在renderpass的这个configure函数里&#xff0c;设置render target 这里的纹理是从shader里map出来的ID&#xff0c;不过我看他文章没…

STM32F1+HAL库+FreeTOTS学习7——列表和列表项

STM32F1HAL库FreeTOTS学习7——列表和列表项 列表和列表项简介列表列表项迷你列表项 列表项API函数介绍1. 初始化列表2. 初始化列表项3. 列表末尾插入列表项4. 列表插入列表项5. 移除列表项6. 补充&#xff1a;FreeRTOS中操作列表和列表项的宏 列表项的插入和删除实验总结 上一…

人工智能时代,AI数据服务行业面临的机遇与挑战

随着大数据、云、物联网、人工智能等信息科技技术的发展以及互联网设备的普及&#xff0c;各行业产生了前所未有海量的AI数据服务需求&#xff0c;彻底宣告了数据时代的来临。 首先&#xff0c;物联网的发展更使线下业务产生的大量数据被采集起来&#xff0c;世界各地的AI数据…