mst[讲课留档]

news2024/11/17 5:42:25

最小生成树(Minimum Spanning Tree)

(1)概念

我们知道,是有 n n n个结点, n − 1 n-1 n1条边的无向无环的连通图。

一个连通图的生成树是一个极小的连通子图,它包含图中全部的 n n n个顶点,但只有构成一棵树的 n − 1 n-1 n1条边。

最小生成树就是一个带权图,每个边都有一个边权,一颗生成树的权值是该树边所有边权的和, M S T MST MST就是所有生成树中最小的一个。

(2)Prim算法(遍历点的算法)

普里姆算法在找最小生成树时,将顶点分为两类,一类是在查找的过程中已经包含在生成树中的顶点(假设为 A 类),剩下的为不在生成树中的(假设为 B 类)。

对于给定的连通网,起始状态全部顶点都归为 B 类。在找最小生成树时,选定任意一个顶点作为起始点,并将之从 B 类移至 A 类;然后找出 B 类中到 A 类中的顶点之间权值最小的顶点,将之从 B 类移至 A 类,如此重复,直到 B 类中没有顶点为止。所走过的顶点和边就是该连通图的最小生成树。

请添加图片描述

int dis[N];
int mp[N][N];
bool vis[N];

void work() {
	int n, m;cin >> n >> m;
	int ans = 0;
    memset(vis, 0, sizeof vis);
    memset(mp, 0x3f3f3f3f, sizeof mp);
    for (int i = 0; i < n; ++i) {
    	int u, v, w;cin >> u >> v >> w;
        mp[u][v] = w;
        mp[v][u] = w;
    }
    for (int i = 0; i < n; ++i) {
        dis[i] = 0x3f3f3f3f;
    }
    dis[0] = 0;
    vis[0] = 1;
    for (int i = 1; i < n; ++i) {
        dis[i] = min(dis[i], mp[0][i]);
    }
    for (int i = 1; i < n; ++i) {
        //这里的外层循环是循环遍数,与i值无关
        double minn = 0x3f3f3f3f;
        int pos = -1;
        for (int j = 1; j < n; ++j) {
            //每次循环找出与已排联通块距离最近的点
            if (!vis[j] && minn > dis[j]) {
                pos = j;
                minn = dis[j];
            }
        }
        ans += minn;
        vis[pos] = 1;
        for (int j = 0; j < n; ++j) {
            //刷新未连接点的距离最小值
            dis[j] = min(dis[j], mp[pos][j]);
        }
    }
    cout << ans << '\n';
}

正确性显然。

复杂度是 O ( n 2 ) O(n^2) O(n2)级别的,但是我们可以使用堆优化降到 O ( n l o g n ) O(nlogn) O(nlogn),之后讲最短路的时候会讲堆优化。

(3)Kruskal算法(遍历边的算法)

克鲁斯卡尔算法(Kruskal)是一种使用贪婪方法的最小生成树算法。 该算法初始将图视为森林,图中的每一个顶点视为一棵单独的树。 一棵树只与它的邻接顶点中权值最小且不违反最小生成树属性(不构成环)的树之间建立连边。

请添加图片描述

利用并查集可以快速实现查找两个点是否已经连接

int n, m;
int f[105];
struct road {
	int a, b, v;
} arr[305];

int find(int a) {
	if (f[a] == a)
		return a;
	else
		return f[a] = find(f[a]);
}

void join(int a, int b) {
	if (find(a) != find(b))
		f[find(a)] = find(b);
}

bool cmp(road a, road b) {
	return a.v < b.v;
}

void work() {
	cin >> n >> m;
	int a, b, c;
	for (int i = 1; i <= n; ++i) {
		f[i] = i;
	}
	int ans = 0;
	for (int i = 0; i < m; ++i) {
		cin >> arr[i].a >> arr[i].b >> arr[i].v;
	}
	sort(arr, arr + m, cmp);
	//先按路的权值排序,如果两点的祖先不是一个就加上然后合并。
	for (int i = 0; i < m; ++i) {
		if (find(arr[i].a) != find(arr[i].b)) {
			ans += arr[i].v;
			join(arr[i].a, arr[i].b);
		}
	}
	cout << ans << '\n';
	return 0;
}

正确性证明:

给一带权连通的树一定会有至少一棵生成树,那么这些生成树中间必然会会存在至少一棵最小生成树。

假设 T T T是用 k r u s k a l kruskal kruskal求出来的最小生成树,而 U U U是这个图的最小生成树,要证 U = T U = T U=T
然而如果 T ≠ U T \neq U T=U,那么至少存在一条边在 T T T中,不在 U U U中,假设存在 k k k条边存在 T T T中不存在 U U U中。
接下来进行 k k k次变换:
每次将在 T T T中不在 U U U中的最小的边 f f f拿出来放到 U U U中,那么 U U U中必然形成一条唯一的环路,我们取出这个环路上最小的且不在 T T T中的边 e e e放回到 T T T中,这样的边 e e e一定是存在的,因为之前的 T T T不存在环路(如果 e e e T T T中那么就可能和 f f f形成环路)。

在这里插入图片描述
现在证明 f f f e e e权值的关系:

假设 f < e f < e f<e,那么后来形成的 U U U是权值之和更小了,与 U U U是最小生成树矛盾。 实际上,不可能在 U U U中拿到大于 f f f的边,因为把 f f f拿走后,如果小于 f f f的边都不成立,至少 f f f是一个符合条件的边会被那回。

假设 f > e f > e f>e,那么根据 k r u s k a l kruskal kruskal的做法, e e e是在 f f f之前被取出来的边但是被舍弃了,一定是因为 e e e和比 e e e小的边形成了环路,而比 e e e小的边都是存在 U U U中的,而 e e e和这些边并没有形成环路,于假设矛盾。

于是 f f f一定和 e e e相等的, k k k次变换后, T T T U U U的权值之和是相等的。

最小生成树的值也是相等的。

复杂度是 O ( n l o g n ) O(nlogn) O(nlogn)级别的,一般有mst就用这个。

int f[N];
struct road {
    int a, b, v;
} arr[N];
int tot = 0;

int find(int a) {
    if (f[a] == a)  return a;
    return f[a] = find(f[a]);
}

void join(int a, int b) {
    if (find(a) != find(b)) f[find(a)] = find(b);
}

bool cmp(road a, road b) {
    return a.v < b.v;
}

void work() {
    int a, b;cin >> a >> b;
    for (int i = 1; i <= b; ++i) {
        f[i] = i;
        arr[i] = {0, i, a};
    }
    tot = b;
    for (int i = 1; i <= b; ++i) {
        for (int j = 1; j <= b; ++j) {
            int x; cin >> x;
            if (x == 0) continue;
            else arr[++tot] = {i, j, x};
        }
    }
    ll ans = 0;
    sort(arr + 1, arr + 1 + tot, cmp);
    for (int i = 1; i <= tot; ++i) {
        if (find(arr[i].a) != find(arr[i].b)) {
            ans += arr[i].v;
            join(arr[i].a, arr[i].b);
            b--;
        }
        if (b == 0) break;
    }
    cout << ans << '\n';
}

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

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

相关文章

实验五 计数器的设计与仿真

仿真 链接&#xff1a;https://pan.baidu.com/s/1N1nR39Gws59laVZY2slzBw 提取码&#xff1a;01ct 一、实验目的 1、通过实验&#xff0c;能熟悉QUARTUS开发环境&#xff0c;能够掌握VHDL设计电路&#xff0c;掌握使用相关仿真工具进行功能和时序仿真的方法&#xff1b; 2、通…

.js.map文件泄露/Springboot信息泄露

目录 框架识别 Webpack 简述 .js.map文件泄露 利用 Spring boot 很多网站都使用的是现有的框架进行开发的&#xff0c;因此相当于很多目录和文件的路径都是开源可知的&#xff0c;因此我们就可以直接访问对应的路径&#xff0c;如果网站没有进行限制就有可能会导致敏感信…

Mac搭建anaconda环境并安装深度学习库

1. 下载anaconda安装包 根据自己的操作系统不同&#xff0c;选择不同的安装包Anaconda3-2024.06-1-MacOSX-x86_64.pkg&#xff0c;我用的还是旧的intel所以下载这个&#xff0c;https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/&#xff0c;如果mac用的是M1&#xff0…

Administrators就最高了???system是什么??本地用户提权内网学习第三天 你知道uac是什么??

我们今天来说说本地用户提权的操作&#xff0c;我们在有webshell过后我们要进行进一步的提权操作&#xff0c;要不然对我们后期的内网渗透会有一些阻碍的操作。比如说我们使用mimikatz来进行抓取密码&#xff0c;就不能够成功。 Administrators与system的区别 我们来说说Admin…

毫米波雷达深度学习技术-1.7训练一个神经网络

1.7 训练一个神经网络 对于训练神经网络&#xff0c;有两个步骤&#xff0c;即前向传递和误差反向传播。 1.7.1 前向传播和反向传播 在前向传递中&#xff0c;输入被馈送到模型并与权重向量相乘&#xff0c;并为每一层添加偏差以计算模型的输出。密集层或全连接层第l层的输入、…

微信小程序的运行机制与更新机制

1. 小程序运行机制 1.1. 冷启动与热启动 冷启动为用户第一次打开小程序时&#xff0c;因为之前没有打开过&#xff0c;这是第一种冷启动的情兑。第二种情况为虽然之前用户打开过&#xff0c;但是小程序被用户主动的销毁过&#xff0c;这种情况下我们再次打开小程序&#xff0…

西门子S120伺服驱动器F1910故障报警处理总结

西门子S120伺服驱动器F1910故障报警处理总结 热压机正常工作时出现故障,无上升和下降动作,伺服故障代码为1910, 同时发现压机的实际压力为13Mpa,没有达到设定的14Mpa, 查看S120的报警手册,如下图所示, F01910:现场总线设定值超时,与上位机控制器的通讯故障, 可能的原…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《考虑复合指标优化模态分解和 Stacking 集成的综合能源系统多元负荷预测》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

巴西东南湾乌巴图巴 ANTARES 监测站数据

ANTARES monitoring station in Ubatuba, Southeast Brazilian Bight 巴西东南湾乌巴图巴 ANTARES 监测站 简介 ANTARES 区域网络由分布在拉丁美洲的沿岸时间序列站组成。主要目的是研究气候和人为影响引起的长期变化&#xff0c;以及用于卫星匹配和算法开发的海洋颜色。Uba…

一分钟学习数据安全—自主管理身份SSI分布式加密密钥管理

在这篇之前&#xff0c;我们已经对SSI有了一个全局的了解。这个系列的文章可以作为一个学习笔记来参考&#xff0c;真正要实践其中的一些方案、协议&#xff0c;还需要参考专业的书籍和官方文档。作为一个SSI系列学习笔记的最后一篇&#xff0c;我们做一个简单的延伸&#xff0…

【PLC】三菱PLC如何和汇川伺服实现485通信

前言 一开始选用的是汇川SV660P脉冲型伺服&#xff0c;由于生产需求需要对伺服的个别参数进行读取和写入操作&#xff0c;但是SV660P并不支持这种情况&#xff0c;因此需要使用485通信来满足。PLC这边选用的是三菱FX5U。 开始 1、首先准备按照下图的引脚提示准备好一根带屏蔽…

(七)glDrawArry绘制

几何数据&#xff1a;vao和vbo 材质程序&#xff1a;vs和fs(顶点着色器和片元着色器) 接下来只需要告诉GPU&#xff0c;使用几何数据和材质程序来进行绘制。 #include <glad/glad.h>//glad必须在glfw头文件之前包含 #include <GLFW/glfw3.h> #include <iostrea…

英伟达经济学:云服务商在GPU上每花1美元 就能赚7美元

NVIDIA超大规模和 HPC 业务副总裁兼总经理 Ian Buck 近日在美国银行证券 2024 年全球技术大会上表示&#xff0c;客户正在投资数十亿美元购买新的NVIDIA硬件&#xff0c;以跟上更新的 AI 大模型的需求&#xff0c;从而提高收入和生产力。 Buck表示&#xff0c;竞相建设大型数据…

flask中解决图片不显示的问题(很细微的点)

我在编写flask项目的时候&#xff0c;在编写html的时候&#xff0c;发现不管我的图片路径如何变化&#xff0c;其就是显示不出来。如下图我框中的地方。 我尝试过使用浏览器打开&#xff0c;是可以的。 一旦运行这个flask项目&#xff0c;就无法显示了。 我查阅资料后。发现…

Kafka-时间轮和延迟操作-源码流程

TimingWheel 字段&#xff1a; buckets&#xff1a;Array.tabulate[TimerTaskList]类型&#xff0c;其每一个项都对应时间轮中的一个时间格&#xff0c;用于保存 TimerTaskList的数组。在TimingWheel中&#xff0c;同一个TimerTaskList中的不同定时任务的到期时间可能 不同&a…

【Dison夏令营 Day 06】用 Python 和 Rich 制作 Wordle克隆(中篇)

在大流行期间&#xff0c;Wordle 在 Twitter 上还算比较流行的一款基于网络的益智游戏&#xff0c;要求玩家每天在六次或更短时间内猜出一个新的五个字母的单词&#xff0c;每个人得到的单词都是一样的。 在本教程中&#xff0c;你将在终端上创建自己的 Wordle 克隆。自 2021 …

【Qt】认识Qt界面Hello world小程序

一.认识Qt界面 1.左边栏 在编辑模式下&#xff0c;左边竖排的两个窗⼝叫做 "边栏" 。 ① 是项⽬⽂件管理窗⼝ ② 是打开⽂件列表窗⼝。 边栏⾥的窗⼝数⽬可以增加&#xff0c;边栏⼦窗⼝标题栏有⼀排⼩按钮&#xff0c;最右边的是关闭按钮&#xff0c;倒数第⼆个是 …

分布式限流:Spring Cloud Gateway 限流

分布式限流&#xff1a;Spring Cloud Gateway 限流 在现代微服务架构中&#xff0c;流量控制是一个至关重要的部分。分布式限流作为一种有效的流量控制手段&#xff0c;能够帮助我们保护系统不被突发的流量冲垮。Spring Cloud Gateway支持多种限流方式。 什么是分布式限流 分…

电影交流平台小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;电影类型管理&#xff0c;留言反馈管理&#xff0c;电影中心管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;电影中心&#xff0c;留言反馈 开发系统&#xff1a;Window…

适用于高海拔地区的工业路由器产品

1、西藏背景 西藏&#xff0c;这个位于中国西南部的神秘之地&#xff0c;以其雄伟壮观、神奇瑰丽的自然风光和深厚的文化底蕴&#xff0c;被无数人视为心中的圣地。这里属于高原性气候&#xff0c;具有气温低、气压低&#xff0c;降水少&#xff0c;生态环境十分恶劣。西藏被誉…