算法学习系列(五十七):最小生成树应用

2024-05-04 19:12

本文主要是介绍算法学习系列(五十七):最小生成树应用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 引言
  • 一、最短网络
  • 二、局域网
  • 三、繁忙的都市
  • 四、联络员

引言

在图论中这个 最小生成树 还是比较的简单的,只有两种算法: P r i m 算法 , K r u s k a l 算法 Prim算法,Kruskal算法 Prim算法,Kruskal算法 。一般来说稠密图就用 P r i m 算法 Prim算法 Prim算法 ,稀疏图就用 K r u s k a l 算法 Kruskal算法 Kruskal算法 ,另外这个 P r i m 算法 Prim算法 Prim算法 和朴素版的 D i j k s t r a 算法 Dijkstra算法 Dijkstra算法 其实是非常的相像的,思想基本也差不多,唯一的区别就是 d i s t dist dist 数组的不同,最小生成树中 d i s t [ i ] dist[i] dist[i] 代表点 i i i集合中的距离,而最短路中 d i s t [ i ] [ j ] dist[i][j] dist[i][j] 代表的就是两点之间的最短距离,然后剩下的就是模板了,本章内容也没啥难的,背包问题做累了,先开一个简单的做做,加油吧!


一、最短网络

标签:最小生成树、prim

思路:首先这个一看就是一个最小生成树问题,数据范围和输入给的信息都说明用 P r i m Prim Prim 算法,然后的话,基本就是模板了,关于模板可以参考我之前的博客: 最小生成树问题 。

题目描述:

农夫约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场。约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场。约翰的农场的编号是1,其他农场的编号是 2∼n。为了使花费最少,他希望用于连接所有的农场的光纤总长度尽可能短。你将得到一份各农场之间连接距离的列表,你必须找出能连接所有农场并使所用光纤最短的方案。输入格式
第一行包含一个整数 n,表示农场个数。接下来 n 行,每行包含 n 个整数,输入一个对角线上全是0的对称矩阵。其中第 x+1 行 y 列的整数表示连接农场 x 和农场 y 所需
要的光纤长度。输出格式
输出一个整数,表示所需的最小光纤长度。数据范围
3≤n≤100每两个农场间的距离均是非负整数且不超过100000。输入样例:
4
0  4  9  21
4  0  8  17
9  8  0  16
21 17 16  0
输出样例:
28

示例代码:

#include <bits/stdc++.h>using namespace std;typedef long long LL;
typedef pair<int,int> PII;
#define x first
#define y secondconst int N = 110, INF = 0x3f3f3f3f;int n;
int g[N][N];
int dist[N];
bool st[N];int Prim()
{memset(dist, 0x3f, sizeof dist);int res = 0;for(int i = 0; i < n; ++i){int t = -1;for(int j = 1; j <= n; ++j){if(!st[j] && (t == -1 || dist[j] < dist[t])) t = j;}if(i && dist[t] == INF) return INF;if(i) res += dist[t];st[t] = true;for(int j = 1; j <= n; ++j) dist[j] = min(dist[j], g[t][j]);}return res;
}int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> n;for(int i = 1; i <= n; ++i){for(int j = 1; j <= n; ++j){cin >> g[i][j];}}cout << Prim() << endl;return 0;
}

二、局域网

标签:最小生成树

思路:首先一眼看出来是最小生成树问题,然后就看要求去除的网线和的最大值,那就是求最小生成树了,然后数据范围显示是一个稀疏图,然后我们可以用 K r u s k a l Kruskal Kruskal 算法,这个算法刚好能够知道哪一条边要用哪条不用,不用的就是遍历时形成回路的那条边,然后加起来就行了,也不用其它的一些值,详情见代码。

题目描述:

某个局域网内有 n 台计算机和 k 条 双向 网线,计算机的编号是 1∼n。由于搭建局域网时工作人员的疏忽,现在局域网内的连接
形成了回路,我们知道如果局域网形成回路那么数据将不停的在回路内传输,造成网络卡的现象。注意:对于某一个连接,虽然它是双向的,但我们不将其当做回路。本题中所描述的回路至少要包含两条不同的连接。两台计算机之间
最多只会存在一条连接。不存在一条连接,它所连接的两端是同一台计算机。因为连接计算机的网线本身不同,所以有一些连线
不是很畅通,我们用 f(i,j) 表示 i,j 之间连接的畅通程度,f(i,j) 值越小表示 i,j 之间连接越通畅。现在我们需要解决回路问题,我们将除去一些连线,使得网络中没有回路且不影响连通性(即如果之前某两个点是连通的,去完
之后也必须是连通的),并且被除去网线的 Σf(i,j) 最大,请求出这个最大值。输入格式
第一行两个正整数 n,k。接下来的 k 行每行三个正整数 i,j,m 表示 i,j 两台计算机之间有网线联通,通畅程度为 m。输出格式
一个正整数,表示被除去网线的 Σf(i,j) 的最大值。数据范围
1≤n≤1000≤k≤200,1≤f(i,j)≤1000
输入样例:
5 5
1 2 8
1 3 1
1 5 3
2 4 5
3 4 2
输出样例:
8

示例代码:

#include <bits/stdc++.h>using namespace std;typedef long long LL;
typedef pair<int,int> PII;
#define x first
#define y secondconst int N = 110, M = 210, INF = 0x3f3f3f3f;int n, m;
int p[N];struct Edge
{int a, b, w;bool operator<(const Edge& other){return w < other.w;}
}edges[M];int find(int x)
{if(x != p[x]) p[x] = find(p[x]);return p[x];
}int Kruskal()
{for(int i = 1; i <= n; ++i) p[i] = i;sort(edges, edges+m);int res = 0;for(int i = 0; i < m; ++i){int a = edges[i].a, b = edges[i].b, w = edges[i].w;a = find(a), b = find(b);if(a != b) p[a] = b;else res += w;}return res;
}int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> n >> m;for(int i = 0; i < m; ++i){int a, b, w; cin >> a >> b >> w;edges[i] = {a,b,w};}cout << Kruskal() << endl;return 0;
}

三、繁忙的都市

标签:最小生成树

思路:由题意得其实就是把路口当作点,然后求最小生成树呢,第一问肯定是 n − 1 n - 1 n1 ,然后第二问可以在选择的点中取最大值即可。这道题的数据范围要用 P r i m Prim Prim 算法来做,该算法中 d i s t [ t ] dist[t] dist[t] 就为选的边,取最大值即可。

题目描述:

城市C是一个非常繁忙的大都市,城市中的道路十分的拥挤,于是市长决定对其中的道路进行改造。城市C的道路是这样分布的:城市中有 n 个交叉路口,编号是 1∼n,有些交叉路口之间有道路相连,两个交叉路口之间最多有一条道路相连接。这些道路是 双向 的,且把所有的交叉路口直接或间接的连接起来了。每条道路都有一个分值,分值越小表示这个道路越繁忙,越需要进行改造。但是市政府的资金有限,市长希望进行改造的道路越少越好,于是他提出下面的要求:1.改造的那些道路能够把所有的交叉路口直接或间接的连通起来。2.在满足要求1的情况下,改造的道路尽量少。3.在满足要求1、2的情况下,改造的那些道路中分值最大值尽量小。作为市规划局的你,应当作出最佳的决策,选择哪些道路应当被修建。输入格式
第一行有两个整数 n,m 表示城市有 n 个交叉路口,m 条道路。接下来 m 行是对每条道路的描述,每行包含三个整数u,v,c 表示交叉路口 u 和 v 之间有道路相连,分值为 c。输出格式
两个整数 s,max,表示你选出了几条道路,分值最大的那条道路的分值是多少。数据范围
1≤n≤300,1≤m≤8000,1≤c≤10000
输入样例:
4 5
1 2 3
1 4 5
2 4 7
2 3 6
3 4 8
输出样例:
3 6

示例代码:

#include <bits/stdc++.h>using namespace std;typedef long long LL;
typedef pair<int,int> PII;
#define x first
#define y secondconst int N = 310, M = 8010, INF = 0x3f3f3f3f;int n, m;
int g[N][N], dist[N];
bool st[N];
int maxv;void Prim()
{memset(dist, 0x3f, sizeof dist);for(int i = 0; i < n; ++i){int t = -1;for(int j = 1; j <= n; ++j){if(!st[j] && (t == -1 || dist[j] < dist[t])) t = j;}if(i) maxv = max(maxv, dist[t]);  // dist[t]为选的边st[t] = true;for(int j = 1; j <= n; ++j) dist[j] = min(dist[j], g[t][j]);}
}int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);memset(g, 0x3f, sizeof g);cin >> n >> m;while(m--){int a, b, w; cin >> a >> b >> w;g[a][b] = g[b][a] = min(g[a][b], w);}Prim();cout << n - 1 << " " << maxv << endl;return 0;
}

四、联络员

标签:最小生成树、Kruskal

思路:首先这道题是一个最小生成树问题,然后一看题意,大体的思路就是先把必须选的选一遍,然后对没有选的做一遍最小生成树就行了,看这个数据范围想着用 P r i m Prim Prim 算法,但是如果拿邻接矩阵来存的话,标记边就不好标记了,然后又想着如果拿 K r u s k a l Kruskal Kruskal 算法的话,因为算法特性可以知道哪条边是怎样的,时间复杂度为 m l o g N mlogN mlogN 数据范围也允许,所以就采用 K r u s k a l Kruskal Kruskal 算法了。然后思路就是刚才说过的,先把必选的加进去,然后对于没有选的最一遍 K r u s k a l Kruskal Kruskal 即可。

题目描述:

Tyvj已经一岁了,网站也由最初的几个用户增加到了上万个用户,随着Tyvj网站的逐步壮大,管理员的数目也越来越多,现在你身
为Tyvj管理层的联络员,希望你找到一些通信渠道,使得管理员两两都可以联络(直接或者是间接都可以)。本题中所涉及的通
信渠道都是 双向 的。Tyvj是一个公益性的网站,没有过多的利润,所以你要尽可能的使费用少才可以。目前你已经知道,Tyvj的通信渠道分为两大类,一类是必选通信渠道,无论价格多少,你都需要把所有的都选择上;还有一类是
选择性的通信渠道,你可以从中挑选一些作为最终管理员联络的通信渠道。数据保证给出的通信渠道可以让所有的管理员联通。注意: 对于某两个管理员 u,v,他们之间可能存在多条通信渠道,你的程序应该累加所有 u,v 之间的必选通行渠道。输入格式
第一行两个整数 n,m 表示Tyvj一共有 n 个管理员,有 m 个通信渠道;第二行到 m+1 行,每行四个非负整数,p,u,v,w 当 p=1 时,表示这个通信渠道为必选通信渠道;当 p=2 时,表示这个通信渠道为
选择性通信渠道;u,v,w 表示本条信息描述的是 u,v 管理员之间的通信渠道,u 可以收到 v 的信息,v 也可以收到 u 的信息,w表示费用。输出格式
一个整数,表示最小的通信费用。数据范围
1≤n≤2000,1≤m≤10000
输入样例:
5 6
1 1 2 1
1 2 3 1
1 3 4 1
1 4 1 1
2 2 5 10
2 2 5 5
输出样例:
9

示例代码:

#include <bits/stdc++.h>using namespace std;typedef long long LL;
typedef pair<int,int> PII;
#define x first
#define y secondconst int N = 2010, M = 1e4+10, INF = 0x3f3f3f3f;int n, m;
int p[N];struct Edge
{int a, b, w, fg;bool operator<(const Edge& other){return w < other.w;}
}edges[M];int find(int x)
{if(x != p[x]) p[x] = find(p[x]);return p[x];
}int Kruskal()
{for(int i = 1; i <= n; ++i) p[i] = i;sort(edges,edges+m);int res = 0;for(int i = 0; i < m; ++i){int a = edges[i].a, b = edges[i].b, w = edges[i].w, fg = edges[i].fg;a = find(a), b = find(b);if(fg == 1){res += w;p[a] = b;}		}for(int i = 0; i < m; ++i){int a = edges[i].a, b = edges[i].b, w = edges[i].w, fg = edges[i].fg;a = find(a), b = find(b);if(fg == 2 && a != b){res += w;p[a] = b;}		}return res;
}int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> n >> m;for(int i = 0; i < m; ++i){int fg, a, b, w; cin >> fg >> a >> b >> w;edges[i] = {a,b,w,fg};}cout << Kruskal() << endl;return 0;
}

这篇关于算法学习系列(五十七):最小生成树应用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/959917

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

AI一键生成 PPT

AI一键生成 PPT 操作步骤 作为一名打工人,是不是经常需要制作各种PPT来分享我的生活和想法。但是,你们知道,有时候灵感来了,时间却不够用了!😩直到我发现了Kimi AI——一个能够自动生成PPT的神奇助手!🌟 什么是Kimi? 一款月之暗面科技有限公司开发的AI办公工具,帮助用户快速生成高质量的演示文稿。 无论你是职场人士、学生还是教师,Kimi都能够为你的办公文