图论——最小生成树

最小生成树
给定一个无向图,在图中选择若干条边把图的所有节点连起来。要求边长之和最小。在图论中,叫做求最小生成树。
prim算法
prim 算法采用的是一种贪心的策略。
每次将离连通部分的最近的点和点对应的边加入的连通部分,连通部分逐渐扩大,最后将整个图连通起来,并且边长之和最小。

prim算法的贪心策略为什么是正确的?

当我们循环到某一部中,当前的连通块为图中绿色虚线内部分,离连通部分的最近的点和点对应的边如下图所示。
在这里插入图片描述
假设最小生成树中不包含这条边,那么为了最后保证联通,当前该点一定会通过其他路径与该连通块连起来,假设通过下图中红色路径。
在这里插入图片描述
红色路径中一定存在下图中橙色两个点,两点间存在一条边,因为灰色两点间边长一定不大于橙色两点间边长,否则一开始我们选择出的就不是灰色的这个点,所以我们如果把橙色两点间的边删掉,换做灰色两个点的连接,同样可以保持联通,并且一定不会得到更差的结果,也正因此肯证明prim算法贪心策略的正确性,每次将离连通部分的最近的点和点对应的边加入的连通部分。

在这里插入图片描述
kruskal算法
将所有边按照边权升序排序,枚举每条边 (a,b),如果这两个点不连通则把这条边加入最小生成树。

kruskal算法的正确性证明

如下图所示,绿色部分分别是两个连通块,当我们枚举到某一步时,存在一条边可以联通这两个连通块。
在这里插入图片描述
我们假设最小生成树中不包含这一条边,那么为了保证这两个连通块最后能够联通,那么这两个点最后肯定会通过其他路径连起来,假设通过下图中红色路径相连。
在这里插入图片描述
在该红色路线中,一定存在橙色和蓝色点对之间的距离不小于灰色点对之间的距离,因为在我们枚举到灰色点对时,橙色点对和蓝色点对之间还没联通,并且此时我们没有选择这两条边。所以该我们把灰色点对之间的边去替换掉橙色点对或者蓝色点对一定可以得到不差于当前的答案,也正因此我们把灰色点对联通是最优的。
在这里插入图片描述

acwing1140.最短网络

最短路算法裸题

#include <iostream>
#include <cstring>
using namespace std;
const int N = 110;
int n;
int g[N][N];
int dist[N];
bool st[N];
int prim()
{int res = 0;memset(dist, 0x3f, sizeof dist);dist[1] = 0;for (int i = 1; i <= n; i ++ ){int t = -1;for (int j = 1; j <= n; j ++ ){if (!st[j] && (t == -1 || (dist[t] > dist[j])))t = j;}st[t] = 1;res += dist[t];for (int j = 1; j <= n; j ++ )dist[j] = min(dist[j], g[t][j]);}return res;
}
int main()
{cin >> n;for (int i = 1; i <= n; i ++ )for (int j = 1; j <= n; j ++ )cin >> g[i][j];int res = prim();cout << res;return 0;
}

acwing1141.局域网

我们将除去一些连线,使得网络中没有回路且不影响连通性(即如果之前某两个点是连通的,去完之后也必须是连通的),所以在我们去掉回路之后得到的是一个生成森林,在前面我们证明了kruskal算法求出一个最小生成树的结果一定是最优的,我们可以用相同的方法证明kruskal只进行到一半,求出的最小生成森林也是最优的。另外本题要求我们求的是需要删除的边长度最大值,那么我们在枚举边时只需要每次将不需要的边的长度加到答案里便可。

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 110, M = 210;
struct Edge{int a, b, w;bool operator< (const Edge &t){return w < t.w;}
}e[M];
int fa[N];
int n, m;
int find(int a)
{return fa[a] == a ? a : fa[a] = find(fa[a]);
}
int main()
{cin >> n >> m;for (int i = 1; i <= m; i ++ ){int a, b, w;cin >> a >> b >> w;e[i] = {a, b, w};}for (int i = 1; i <= n; i ++ ) fa[i] = i;int res = 0;sort(e + 1, e + m + 1);for (int i = 1; i <= m; i ++ ){int a = e[i].a, b = e[i].b, w = e[i].w;if (find(a) != find(b)) fa[fa[a]] = b;else res += w;}cout << res;return 0;
}

acwing1142.繁忙的都市

1.改造的那些道路能够把所有的交叉路口直接或间接的连通起来。
2.在满足要求1的情况下,改造的道路尽量少。
3.在满足要求1、2的情况下,改造的那些道路中分值最大值尽量小。

首先很显然,为了将所有的边都连通起来,我们改造的道路数为n-1,即一棵生成树,另外本题要求道路中分值最大值尽量小,即求最小瓶颈生成树,而一般的最小生成树问题要求的时边权之和最小。我们可以证明一颗最小生成树一定是最小瓶颈生成树,证明方式和我们一开始最小生成树的证明相同,所以我们可以直接用最短路算法来做,枚举到的长度最长的边就是答案。

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 310, M = 8010;
struct Edge{int a, b, w;bool operator< (const Edge &t) const{return w < t.w;}
}e[M];
int fa[N];
int n, m;
int find(int a)
{return fa[a] == a ? a : fa[a] = find(fa[a]);
}
int main()
{cin >> n >> m;for (int i = 1; i <= n; i ++ )fa[i] = i;for (int i = 1; i <= m; i ++ ){int a, b, c;cin >> a >> b >> c;e[i] = {a, b, c};}int res = 0;sort(e + 1, e + m + 1);for (int i = 1; i <= m; i ++ ){int a = find(e[i].a), b = find(e[i].b), w = e[i].w;if (a != b){fa[a] = b;res = w;}}cout << n - 1 << " " << res;return 0;
}

acwing1143.联络员

本题图中存在一些固定的边,要求我们增加一些新的边来让节点之间联通。

我们可以利用Kruskal,算法,思考一下,既然第1类边是必须选择的,那我们在读入的时候就直接把所有第1类边的权值加到我们的总边权中,并将它们统计到判断图是否连通的并查集里,然后照常做Kruskal就行。

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 2010, M = 10010;
struct Edge{int a, b, w;bool operator< (const Edge &t) const{return w < t.w;}
}e[M];
int fa[N];
int n, m;
int find(int a)
{return fa[a] == a ? a : fa[a] = find(fa[a]);
}
int main()
{cin >> n >> m;int k = 0;for (int i = 1; i <= n; i ++ )fa[i] = i;int res = 0;while (m -- ){int a, b, w, type;cin >> type >> a >> b >> w;if (type == 1){res += w;fa[find(a)] = find(b);}else e[++ k] = {a, b, w};}sort(e + 1, e + k + 1);for (int i = 1; i <= k; i ++ ){int a = find(e[i].a), b = find(e[i].b), w = e[i].w;if (a != b){res += w;fa[a] = b;}}cout << res;return 0;
}

acwing1144.连接格点

本题和上一题的核心思想是完全一样的,只不过本题涉及到了网格图和二维转一维,数据处理会稍微麻烦一些。

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010, M = N * N * 2, K = N * N;
int g[N][N];
int fa[N];
struct Edge{int a, b, w;bool operator< (const Edge &t) const{return w < t.w;}
}e[M];
int n, m;
int cnt = 0;
int find(int a)
{fa[a] == a ? a : fa[a] = find(fa[a]);
}
void get_edges()
{int dx[] = {0, -1, 0, 1}, dy[] = {-1, 0, 1, 0}, dw[] = {2, 1, 2, 1};for (int i = 1; i <= n; i ++ ){for (int j = 1; j <= m; j ++ ){for (int u = 2; u <= 3; u ++ ){int x = i + dx[u], y = j + dy[u];if (x == n + 1 || y == m + 1) continue;int a = g[i][j], b = g[x][y];e[++ cnt] = {a, b, dw[u]};}}}
}
int main()
{cin >> n >> m;int x1, y1, x2, y2;for (int i = 1; i <= n; i ++ )for (int j = 1; j <= n; j ++ )g[i][j] = ++ cnt;cnt = 0;get_edges();for (int i = 1; i <= n * m; i ++ )fa[i] = i;while (cin >> x1 >> y1 >> x2 >> y2){int a = g[x1][y1], b= g[x2][y2];a = find(a), b = find(b);fa[a] = b;}int res = 0;sort(e + 1, e + cnt + 1);for (int i = 1; i <= cnt; i ++ ){int a = find(e[i].a), b = find(e[i].b), w = e[i].w;if (a != b){fa[a] = b;res += w;}}cout << res;return 0;
}

最小生成树扩展应用

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jvisualvm工具使用

jvisualvm 是JDK自带的具有图形界面操作功能的JVM性能监控和诊断工具&#xff0c;它不仅能分析和诊断堆转储文件&#xff0c;在线实时监控本地JVM进程&#xff0c;还能监控远程服务器上的JVM进程。 1 分析服务器下载dump文件 1&#xff09;在我们在安装JDK的bin目录双击jvisa…

C++ list

list需知&#xff1a; list不会出现insert迭代器失效问题 链表插入不会影响原有数据相对位置&#xff0c;且不用扩容 但是erase会导致相对数据位置移动&#xff0c;所有其erase会导致迭代器失效 list排序效率很低 不建议使用 小规模数据量可以使用&#xff0c;比较方便 此外…

DeepSeek-R1 论文解读 —— 强化学习大语言模型新时代来临?

近年来&#xff0c;人工智能&#xff08;AI&#xff09;领域发展迅猛&#xff0c;大语言模型&#xff08;LLMs&#xff09;为通用人工智能&#xff08;AGI&#xff09;的发展开辟了道路。OpenAI 的 o1 模型表现非凡&#xff0c;它引入的创新性推理时缩放技术显著提升了推理能力…

【基于SprintBoot+Mybatis+Mysql】电脑商城项目之用户注册

&#x1f9f8;安清h&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;【计算机网络】【Mybatis篇】 &#x1f6a6;作者简介&#xff1a;一个有趣爱睡觉的intp&#xff0c;期待和更多人分享自己所学知识的真诚大学生。 目录 &#x1f3af;项目基本介绍 &#x1f6a6;项…

蓝桥杯思维训练营(一)

文章目录 题目总览题目详解翻之一起做很甜的梦 蓝桥杯的前几题用到的算法较少&#xff0c;大部分考察的都是思维能力&#xff0c;方法比较巧妙&#xff0c;所以我们要积累对应的题目&#xff0c;多训练 题目总览 翻之 一起做很甜的梦 题目详解 翻之 思维分析&#xff1a;一开…

【AI】DeepSeek 概念/影响/使用/部署

在大年三十那天&#xff0c;不知道你是否留意到&#xff0c;“deepseek”这个词出现在了各大热搜榜单上。这引起了我的关注&#xff0c;出于学习的兴趣&#xff0c;我深入研究了一番&#xff0c;才有了这篇文章的诞生。 概念 那么&#xff0c;什么是DeepSeek&#xff1f;首先百…

minimind - 从零开始训练小型语言模型

大语言模型&#xff08;LLM&#xff09;领域&#xff0c;如 GPT、LLaMA、GLM 等&#xff0c;虽然它们效果惊艳&#xff0c; 但动辄10 Bilion庞大的模型参数个人设备显存远不够训练&#xff0c;甚至推理困难。 几乎所有人都不会只满足于用Lora等方案fine-tuing大模型学会一些新的…

【机器学习】自定义数据集 使用pytorch框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测,对预测结果计算精确度和召回率及F1分数

一、使用pytorch框架实现逻辑回归 1. 数据部分&#xff1a; 首先自定义了一个简单的数据集&#xff0c;特征 X 是 100 个随机样本&#xff0c;每个样本一个特征&#xff0c;目标值 y 基于线性关系并添加了噪声。将 numpy 数组转换为 PyTorch 张量&#xff0c;方便后续在模型中…

数据分析系列--④RapidMiner进行关联分析(案例)

一、核心概念 1.项集&#xff08;Itemset&#xff09; 2.规则&#xff08;Rule&#xff09; 3.支持度&#xff08;Support&#xff09; 3.1 支持度的定义 3.2 支持度的意义 3.3 支持度的应用 3.4 支持度的示例 3.5 支持度的调整 3.6 支持度与其他指标的关系 4.置信度&#xff0…

国产之光DeepSeek架构理解与应用分析

目录 初步探索DeepSeek的设计 一、核心架构设计 二、核心原理与优化 三、关键创新点 四、典型应用场景 五、与同类模型的对比优势 六、未来演进方向 从投入行业生产的角度看 一、DeepSeek的核心功能扩展 二、机械电子工程产业中的具体案例 1. 预测性维护&#xff08;Predictive…

Golang :用Redis构建高效灵活的应用程序

在当前的应用程序开发中&#xff0c;高效的数据存储和检索的必要性已经变得至关重要。Redis是一个快速的、开源的、内存中的数据结构存储&#xff0c;为各种应用场景提供了可靠的解决方案。在这个完整的指南中&#xff0c;我们将学习什么是Redis&#xff0c;通过Docker Compose…

基于互联网+智慧水务信息化整体解决方案

智慧水务的概述与发展背景 智慧水务是基于互联网、云计算、大数据、物联网等先进技术&#xff0c;对水务行业的工程建设、生产管理、管网运营、营销服务及企业综合管理等业务进行全面智慧化管理的创新模式。它旨在解决水务企业分散经营、管理水平不高、投资不足等问题。 水务…

力扣动态规划-16【算法学习day.110】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;建议灵神的题单和代码随想录&#xff09;和记录自己的学习过程&#xff0c;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关…

使用 Tauri 2 + Next.js 开发跨平台桌面应用实践:Singbox GUI 实践

Singbox GUI 实践 最近用 Tauri Next.js 做了个项目 - Singbox GUI&#xff0c;是个给 sing-box 用的图形界面工具。支持 Windows、Linux 和 macOS。作为第一次接触这两个框架的新手&#xff0c;感觉收获还蛮多的&#xff0c;今天来分享下开发过程中的一些经验~ 为啥要做这个…

langgraph实现 handsoff between agents 模式 (1)

官网示例代码 from typing_extensions import Literal from langchain_core.messages import ToolMessage from langchain_core.tools import tool from langgraph.graph import MessagesState, StateGraph, START from langgraph.types import Command from langchain_openai…

Redis代金卷(优惠卷)秒杀案例-单应用版

优惠卷表:优惠卷基本信息,优惠金额,使用规则 包含普通优惠卷和特价优惠卷(秒杀卷) 优惠卷的库存表:优惠卷的库存,开始抢购时间,结束抢购时间.只有特价优惠卷(秒杀卷)才需要填写这些信息 优惠卷订单表 卷的表里已经有一条普通优惠卷记录 下面首先新增一条秒杀优惠卷记录 { &quo…

观察者模式和订阅发布模式的关系

有人把观察者模式等同于发布订阅模式&#xff0c;也有人认为这两种模式存在差异&#xff0c;本质上就是调度的方法不同。 发布订阅模式: 观察者模式: 相比较&#xff0c;发布订阅将发布者和观察者之间解耦。&#xff08;发布订阅有调度中心处理&#xff09;

Ethflow Round 1 (Codeforces Round 1001, Div. 1 + Div. 2)(A,B,C,E1)

题目链接&#xff1a;Dashboard - Ethflow Round 1 (Codeforces Round 1001, Div. 1 Div. 2) - Codeforces A. String 思路 可以发现最小反转次数就是把每个1单独反转为0就行&#xff0c;即统计1的个数 代码 void solve(){string s;cin>>s;int sum0;for(int i0;i&l…

FreeRTOS从入门到精通 第十五章(事件标志组)

参考教程&#xff1a;【正点原子】手把手教你学FreeRTOS实时系统_哔哩哔哩_bilibili 一、事件标志组简介 1、概述 &#xff08;1&#xff09;事件标志位是一个“位”&#xff0c;用来表示事件是否发生。 &#xff08;2&#xff09;事件标志组是一组事件标志位的集合&#x…

Leetcode:541

1&#xff0c;题目 2&#xff0c;思路 用List集合来装字符串其中每k个为一个元素单位我们根据题目意思就可以明白list中偶数位需要反转reverse&#xff0c;奇数保持原样再全部拼接一块最后return tostring 3&#xff0c;代码 import java.util.ArrayList; import java.util.…