最小生成树(Kruskal Prim)
最小生成树
(克鲁斯卡尔算法) Kruskal
给定一个n个点m条边的无向图,图中可能存在重边和自环,边权可能为负数。
求最小生成树的树边权重之和,如果最小生成树不存在则输出impossible。
给定一张边带权的无向图 \(G=(V, E)\),其中\(V\)表示图中点的集合,\(E\)表示图中边的集合,\(n=|V|\),\(m=|E|\)。
由\(V\)中的全部\(n\)个顶点和\(E\)中\(n-1\)条边构成的无向连通子图被称为G的一棵生成树,其中边的权值之和最小的生成树被称为无向图G的最小生成树。
输入格式
第一行包含两个整数n和m。
接下来m行,每行包含三个整数\(u,v,w\),表示点u和点v之间存在一条权值为w的边。
输出格式
共一行,若存在最小生成树,则输出一个整数,表示最小生成树的树边权重之和,如果最小生成树不存在则输出impossible。
数据范围
\(1 \leq n \leq 10^5\)
\(1 \leq m \leq 2∗10^5\)
图中涉及边的边权的绝对值均不超过1000。
输入样例:
4 5
1 2 1
1 3 2
1 4 3
2 3 2
3 4 4
输出样例:
6
思路:
\(Kruskal\)主要用于稀疏图, 用邻接矩阵来处理,时间复杂度为\(O(mlogn)\)。按照边的权重顺序(从小到大)将边加入生成树中,但是若加入该边会与生成树形成环则不加入该边。直到树中含有\(V-1\)条边为止。这些边组成的就是该图的最小生成树。
来自维基百科 原作者:Schulllz
其中如果生成树如果与将要加入的边生成环则说明\((a,b)\)同祖先, 比如上图那种情况, 因此我们这里就可以使用并查集来判断,如果不会生成环中, 则a != b
一定会成立。
代码:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 100010, M = 200010, INF = 0X3f3f3f3f;
int n, m;
int p[N];
struct Edge
{
int a, b, w;
bool operator< (const Edge &W)const //重载运算符
{
return w < W.w;
}
}edges[M];
int find(int x)
{
if(p[x] != x) p[x] = find(p[x]);
return p[x];
}
int kruskal()
{
sort(edges, edges + m);
for(int i = 1; i <= n; i++) p[i] = i;
int res = 0, cnt = 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;
res += w;
cnt++;
}
}
if(cnt < n-1) return INF; //找不到n-1条边肯定有的不连通
return res;
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 0; i < m; i++)
{
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
edges[i] = {a, b, w};
}
int t = kruskal();
if(t == INF) puts("impossible");
else printf("%d\n", t);
return 0;
}
(普利姆算法) Prim
给定一个n个点m条边的无向图,图中可能存在重边和自环,边权可能为负数。
求最小生成树的树边权重之和,如果最小生成树不存在则输出impossible。
给定一张边带权的无向图\(G=(V, E)\),其中\(V\)表示图中点的集合,\(E\)表示图中边的集合,\(n=|V|,m=|E|\)。
由\(V\)中的全部\(n\)个顶点和\(E\)中\(n-1\)条边构成的无向连通子图被称为\(G\)的一棵生成树,其中边的权值之和最小的生成树被称为无向图\(G\)的最小生成树。
输入格式
第一行包含两个整数\(n\)和\(m\)。
接下来\(m\)行,每行包含三个整数\(u,v,w\)表示点\(u\)和点\(v\)之间存在一条权值为\(w\)的边。
输出格式
共一行,若存在最小生成树,则输出一个整数,表示最小生成树的树边权重之和,如果最小生成树不存在则输出impossible。
数据范围
\(1 \leq n \leq 500\)
\(1 \leq m \leq 10^5\)
图中涉及边的边权的绝对值均不超过10000。
输入样例:
4 5
1 2 1
1 3 2
1 4 3
2 3 2
3 4 4
输出样例:
6
思路
\(Prim\)主要用于稠密图, 用邻接表来处理,时间复杂度为\(O(n^2)\)
void Prim()
{
dist[i] = +∞
for (int i = 0; i < n; i++)
{
1.t<-集合外距离最近的点
st[t] = true //标记
2.用t更新其他点到集合的距离
}
}
代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 510, INF = 0x3f3f3f3f;
int n, m;
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[t] > dist[j]))
{
t = j;
}
}
if(i && dist[t] == INF) return INF; //说明不存在最小生成树 由V中的全部n个顶点和E中n-1条边构成的无向连通子图被称为G的一棵生成树,
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()
{
scanf("%d%d", &n, &m);
memset(g, 0x3f, sizeof g);
while(m--)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
g[a][b] = g[b][a] = min(g[a][b], c);
}
int t = prim();
if(t == INF) puts("impossible");
else printf("%d\n", t);
return 0;
}
最小生成树(Kruskal Prim)的更多相关文章
- POJ1251 Jungle Roads (最小生成树&Kruskal&Prim)题解
题意: 输入n,然后接下来有n-1行表示边的加边的权值情况.如A 2 B 12 I 25 表示A有两个邻点,B和I,A-B权值是12,A-I权值是25.求连接这棵树的最小权值. 思路: 一开始是在做莫 ...
- 最小生成树之 prim算法和kruskal算法(以 hdu 1863为例)
最小生成树的性质 MST性质:设G = (V,E)是连通带权图,U是V的真子集.如果(u,v)∈E,且u∈U,v∈V-U,且在所有这样的边中, (u,v)的权c[u][v]最小,那么一定存在G的一棵最 ...
- 最小生成树算法prim and kruskal
一.最小生成树定义: 从不同顶点出发或搜索次序不同,可得到不同的生成树 生成树的权:对连通网络来说,边附上权,生成树也带权,我们把生成树各边的权值总和称为生成树的权 最小代价生成树:在一个连通网 ...
- C++编程练习(10)----“图的最小生成树“(Prim算法、Kruskal算法)
1.Prim 算法 以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树. 2.Kruskal 算法 直接寻找最小权值的边来构建最小生成树. 比较: Kruskal 算法主要是针对边来展开,边数 ...
- java实现最小生成树的prim算法和kruskal算法
在边赋权图中,权值总和最小的生成树称为最小生成树.构造最小生成树有两种算法,分别是prim算法和kruskal算法.在边赋权图中,如下图所示: 在上述赋权图中,可以看到图的顶点编号和顶点之间邻接边的权 ...
- 无向带权图的最小生成树算法——Prim及Kruskal算法思路
边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以 ...
- 最小生成树(prim和kruskal)
最小生成树(prim和kruskal) 最小生成树的最优子结构性质 设一个最小生成树是T.如果选出一个T中的一条边,分裂成的两个树T1,T2依然是它们的点集组成的最小生成树.这可以用反证法来证.反着来 ...
- 数据结构(三十三)最小生成树(Prim、Kruskal)
一.最小生成树的定义 一个连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树的n-1条边. 在一个网的所有生成树中,权值总和最小的生成树称为最小代价生成树(Minimum ...
- 最小生成树——Kruskal与Prim算法
最小生成树——Kruskal与Prim算法 序: 首先: 啥是最小生成树??? 咳咳... 如图: 在一个有n个点的无向连通图中,选取n-1条边使得这个图变成一棵树.这就叫“生成树”.(如下图) 每个 ...
- MST最小生成树及Prim普鲁姆算法
MST在前面学习了Kruskal算法,还有一种算法叫做Prim的.这两者的区别是Prim算法适合稠密图,比如说鸟巢这种几乎所有点都有相连的图.其时间复杂度为O(n^2),其时间复杂度与边的数目无关:而 ...
随机推荐
- LCD与OLED的相爱相杀
目前市面的显示技术主要分为LCD与OLED. 本文主要记录对LCD与OLED的学习. 导言:介绍一些专业名词和术语. 像素点:是指在由一个数字序列表示的图像中的一个最小单位,称为像素. 一张图片在显示 ...
- XCTF-CGfsb
考察知识点 PWN.格式化字符串漏洞 题目链接 https://adworld.xctf.org.cn/task/answer?type=pwn&number=2&grade=0&am ...
- 【游记】NOIP2022 预备赛游记
Day -2 \(NOIP\) 就要来了,\(CSYZ\) 斥巨资给我们在 \(NOIP\) 正式考点举办了一场 \(NOIP\) 预备赛,真是太感动了~~ \(cy\) 说明天要颁奖,激动激动! D ...
- 给DataTable添加额外字段
//dt为DataTable dt.Columns.Add("字段名");//创建字段 //给新增字段赋值 foreach(DataRow item in dt.Rows) { i ...
- AI测试,给出的答案还挺那么回事儿的~
今天文心一言全民开放了,所有人都可以正常下载使用了,不用像之前一样排队等号了.之前内测阶段倒也体验过,技术人员总是喜欢尝鲜,第一时间拿到邀请码后就各种调戏了TA一番,那时觉得给出的答案总有些差强人意, ...
- 给你的 SpringBoot 工程部署的 jar 包瘦瘦身吧!
之前有写过一篇有关maven插件的文章:spring-boot-maven-plugin插件详解 一.需求背景 我们知道Spring Boot项目,是可以通过java -jar 包名 启动的. 那为什 ...
- redhat7 team bonding 双网卡绑定 主备 负载均衡
team简介 team也被称为网络组,是将多个网卡聚合在一起,从而实现冗错和提高吞吐量.适用于redhat7.0以上版本,至多可支持8块网卡.team相对于之前的bonding技术,能提供更好的性能和 ...
- Springboot多种字段copy工具比较
结论:推荐使用spring自带的copy工具,不能copy的手动set 1.springboot自带的BeanUtils.copyProperties package com.admin; impor ...
- FX3U-3A-ADP模拟量和数字量之间转换
简单的例子: 0-10V对应0-8,4-20mA对应0-30 以下是对上面例子的详解: 电压: 电压(0-10V) 0-10V对应着数字量0-4000 数字量与变频器HZ量之间的关系是(4000-0) ...
- MySQL系列之优化——1.优化哲学、2. 优化工具的使用、3. 优化思路分解、4. MySQL参数优化测试、5.1 参数优化、6. 参数优化结果、7. 锁的监控及处理、8. 主从优化
文章目录 1.优化哲学 1.1 为什么优化? 1.2 优化风险 1.3 谁参与优化 1.4 优化方向 1.5 优化的范围及思路 优化效果和成本的评估: 2. 优化工具的使用 2.1 系统层面的 2.1 ...