最小生成树两个经典算法(Prime算法、Kruskal算法) - biaobiao88
经典的最小生成树例子,Prime算法,具体的步骤及其注释本人均在代码中附加,请仔细阅读与品味,要求,可以熟练的打出。
//Prime算法基础
#include<iostream>
using namespace std; int main()
{
int n,m,i,j,k,min,t1,t2,t3;
int e[][],dis[],book[] = {};
int inf = ;
int count = ,sum = ;
cin >> n >> m; //初始化 用邻接矩阵存储
for(int i = ;i <= n;i++)
for(int j = ;j <= n;j++)
if(i == j)
e[i][j] = ;
else
e[i][j] = inf; //读入边 无向图来回都得设置权值
for(int i = ;i <= m;i++)
{
cin >> t1 >> t2 >> t3;
e[t1][t2] = t3;
e[t2][t1] = t3;
} //初始化dis数组,这里是第一个顶点到各个顶点的初始距离,因为当前生成树中只有一个顶点
for(int i = ;i <= n;i++)
dis[i] = e[][i]; //Prime核心部分
//将第一个顶点(即1号顶点)加入生成树
book[] = ;//这里用book数组来标记一个顶点是否已经加入生成树
count++;//表示生成树中已加入一个顶点
while(count < n)
{
min = inf; //扫描找出距离当前根顶点相连接的最小权值的顶点
for(int i = ;i <= n;i++)
{
if(book[i] == && min > dis[i])//如果根节点未被标记并且根节点到剩下的n-1个顶点之间有直连线(就是相连着的边)
{
min = dis[i];//就将这条边的权值代替之前初始化时的无穷大 ,更新min的值,min的值更新只在此for循环中有效,此for循环目的是找出连接根节点权值最小的那个顶点j,再把min放入for循环中,一直比较,直至找到最小的权值及连的顶点j
j = i;//同时将此时的顶点的编号记录在临时变量j中,以便接下来使用
}
}
book[j] = ;//将上面for循环中找到的最小权值的顶点j加入到生成树中并标记
count++;//生成树中的顶点加一
sum += dis[j];//将权值最小的边都累加,最终得到最优解 //扫描当前顶点j所有的边,再以j为中心点,更新生成树到每一个非树顶点的距离
for(k = ;k <= n;k++)
{
if(book[k] == && dis[k] > e[j][k])//e[k]表示第一个加入的根顶点到顶点k之间的权值(可能直接连接也可能间接连接),e[j][k]表示的是当前根顶点作为j,到与j顶点直接相连的顶点k的权值
dis[k] = e[j][k];//此循环的目的是找出离j顶点最近的顶点
}
}
cout << sum;
return ;
}
/*
6 9
2 4 11
3 5 13
4 6 3
5 6 4
2 3 6
4 5 7
1 2 1
3 4 9
1 3 2
19
*/
运行结果:
Kruskal算法,需要用到并查集,具体请看以下代码
//Kruskal算法
#include<iostream>
#include<algorithm>
using namespace std;
struct edge
{
int u;
int v;
int w;
}e[];//为了方便排序,这里创建了一个结构体数组来存储边的关系,数组大小根据实际情况来设置,要比m的最大值大1
int n,m;
int f[],sum = ,countt = ;//并查集需要用到的一些变量,f数组大小根据实际情况来设置,要比n的最大值大1 ////这个也是快速排序,也可以替代sort函数
//void quicksort(int left,int right)
//{
// int i,j;
// struct edge t;
// if(left > right)
// return;
// i = left;
// j = right;
// while(i != j)
// {
// //顺序很重要,要先从右边开始找
// while(e[j].w >= e[left].w && i < j)
// j--;
// //再从左边开始找
// while(e[i].w <= e[left].w && i < j)
// i++;
// //交换
// if(i < j)
// {
// t = e[i];
// e[i] = e[j];
// e[j] = t;
// }
// }
// //最终将基准数归位,将left和i互换
// t = e[left];
// e[left] = e[i];
// e[i] = t;
//
// quicksort(left,i - 1);//继续处理左边的,这里是一个递归的过程
// quicksort(i + 1,right);//继续处理右边的,这里是一个递归的过程
// return;
//} //并查集寻找祖先的函数
int getf(int v)
{
if(f[v] == v)
return v;
else
{
//这里是路径压缩
f[v] = getf(f[v]);
return f[v];
}
}
//并查集合并两个子集合的函数
int merge(int v,int u)
{
int t1,t2;
t1 = getf(v);
t2 = getf(u);
if(t1 != t2)//判断两个点是否在同一个集合中
{
f[t2] = t1;
return ;
}
return ;
} bool cmp(const edge &a,const edge &b)
{
return a.w < b.w;
} int main()
{
//读入顶点个数n和边的条数m
cin >> n >> m;
//读入边,这里用结构体数组来存储边的关系
for(int i = ;i <= m;i++)
cin >> e[i].u >> e[i].v >> e[i].w;
// quicksort(1,m);//按照权值从大到小对边进行快速排序
//快速排序权值
sort(e + ,e + m + ,cmp);
//并查集初始化
for(int i = ;i <= n;i++)
f[i] = i; //Kruskal算法核心部分
for(int i = ;i <= m;i++)
{
//判断一条边的两个顶点是否已经连通,即判断是否已在同一个集合中
if(merge(e[i].u,e[i].v))//如果目前不连通,则选用这条边
{
countt++;//满足条件将顶点加入生成树
sum += e[i].w;//路径累加和
}
if(countt == n - )//当顶点均加入到生成树中时,结束循环
break;
}
cout << sum << endl;
return ;
}
运行结果:
并查集例题

下面是对并查集使用的代码,并查集不太理解的可以看看下面的代码
//并查集的使用
#include<iostream>
using namespace std;
int f[],n,m,k,sum; //这是找爹的递归函数,不停的去找爹,直到找到祖宗为止,即找到根节点,这个函数的目的是判断两个顶点是否属于同一个集合
int getf(int v)
{
if(f[v] == v)
return v;
else
{
/*这里是路径压缩,每次在函数返回的时候,顺带把同一个集合里面的元素都改为根节点的祖先编号,这样可以提高今后找到树的祖先的速度*/
f[v] = getf(f[v]);
return f[v];
}
}
//这里是合并两子集合的函数,在合并函数中调用getf函数,看两个顶点是否是属于同一个集合,然后再决定是否执行合并操作
void merge(int v,int u)
{
int t1,t2;
t1 = getf(v);
t2 = getf(u);
if(t1 != t2)//根据调用getf的函数,判断两个顶点是否在同一个集合中,即是否为同一个祖先
{
f[t2] = t1;
}
} int main()
{
int x,y;
cin >> n >> m;
//这里是初始化,非常的重要,数组里面存的是自己数组下标的编号就好了
for(int i = ;i <= n;i++)
f[i] = i;
for(int i = ;i <= m;i++)
{
cin >> x >> y;
merge(x,y);//将两个顶点传入合并集合函数中进行操作
}
for(int i = ;i <= n;i++)
{
if(f[i] == i)//根节点的值依旧是原先的值,即判断有几个顶点的值不变即有几个不同的集合
sum++;
}
cout << sum << endl;
return ;
}
/*
10 9
1 2
3 4
5 2
4 6
2 6
8 7
9 7
1 6
2 4
3
*/
运行结果:
✌
最小生成树两个经典算法(Prime算法、Kruskal算法) - biaobiao88的更多相关文章
- 算法起步之Kruskal算法
原文:算法起步之Kruskal算法 说完并查集我们接着再来看这个算法,趁热打铁嘛.什么是最小生成树呢,很形象的一个形容就是铺自来水管道,一个村庄有很多的农舍,其实这个村庄我们可以看成一个图,而农舍就是 ...
- 无向带权图的最小生成树算法——Prim及Kruskal算法思路
边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以 ...
- [数据结构]最小生成树算法Prim和Kruskal算法
最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树. 例如,对于如上图G4所示的连通网可以有多棵权值总 ...
- 最小生成树(MST)Prim算法和Kruskal算法
刚学完最小生成树,赶紧写写学习的心得(其实是怕我自己忘了) 最小生成树概念:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边. 就是说 ...
- ZOJ 1542 POJ 1861 Network 网络 最小生成树,求最长边,Kruskal算法
题目连接:problemId=542" target="_blank">ZOJ 1542 POJ 1861 Network 网络 Network Time Limi ...
- 算法(图论)——最小生成树及其题目应用(prim和Kruskal算法实现)
题目 n个村庄间架设通信线路,每个村庄间的距离不同,如何架设最节省开销? Kruskal算法 特点 适用于稀疏图,时间复杂度 是nlogn的. 核心思想 从小到大选取不会产生环的边. 代码实现 代码中 ...
- 算法笔记_066:Kruskal算法详解(Java)
目录 1 问题描述 2 解决方案 2.1 构造最小生成树示例 2.2 伪码及时间效率分析 2.3 具体编码(最佳时间效率) 1 问题描述 何为Kruskal算法? 该算法功能:求取加权连通图的最小 ...
- 算法8-4:Kruskal算法
Kruskal算法用于计算一个图的最小生成树.这个算法的过程例如以下: 依照边的权重从小到达进行排序 依次将每条边添加到最小生成树中,除非这条边会造成回路 实现思路 第一个步骤须要对边进行排序,排序方 ...
- 最小生成树(prime算法 & kruskal算法)和 最短路径算法(floyd算法 & dijkstra算法)
一.主要内容: 介绍图论中两大经典问题:最小生成树问题以及最短路径问题,以及给出解决每个问题的两种不同算法. 其中最小生成树问题可参考以下题目: 题目1012:畅通工程 http://ac.jobdu ...
随机推荐
- Kafka 学习笔记之 架构
Kafka的概念: 1. AMQP协议 Advanced Message Queuing Protocol (高级消息队列协议) The Advanced Message Queuing Protoc ...
- tensorflow中添加L2正则化损失
方法有几种,总结一下方便后面使用. 1. tensorflow自动维护一个tf.GraphKeys.WEIGHTS集合,手动在集合里面添加(tf.add_to_collection())想要进行正则化 ...
- 构造函数语义学——Default Constructor篇
构造函数语义学--Default Constructor 篇 这一章原书主要分析了:编译器关于对象构造过程的干涉,即在对象构造这个过程中,编译器到底在背后做了什么 这一章的重点在于 default c ...
- springboot 快速开发的定制补充
增强 SpringBoot 快速开发工具 项目地址:https://gitee.com/sanri/web-ui 优点:这是一个 web 通用配置的组件,即插即用,可用于新项目或私活.是对 Sprin ...
- [JZOJ100047] 【NOIP2017提高A组模拟7.14】基因变异
Description 21 世纪是生物学的世纪,以遗传与进化为代表的现代生物理论越来越多的 进入了我们的视野. 如同大家所熟知的,基因是遗传因子,它记录了生命的基本构造和性能. 因此生物进化与基因的 ...
- Python eval() exec()
eval(str) 函数:将字符串 str 当成有效的表达式来求值并返回计算结果常见作用:1,计算字符串中有效的表达式,并返回结果In [55]: eval('pow(10,2)') # 函数Out[ ...
- opencv::卷积运算函数filter2D()
opencv::卷积运算函数filter2D() 使用掩模板矩阵(kernel)计算每个像素值 与原图相比,没有黑边 int main(int argc, char** argv) { Mat src ...
- VoodooPad Mac笔记本
VoodooPad Mac笔记本 VoodooPad是记录您的笔记和想法的地方.想法,图片,列表,密码和妈妈的苹果派食谱.包括您需要跟踪和组织的所有内容,VoodooPad会与您一起成长而不会妨碍您. ...
- Bootstrap Studio Mac网页设计神器
Bootstrap Studio Mac网页设计神器 美丽的组件 Bootstrap Studio附带了大量漂亮的组件,用于构建响应式页面.我们有页眉,页脚,画廊,幻灯片甚至基本元素,如跨度和div. ...
- 02jmeter-函数助手使用
示例:__Random函数 1.打开函数助手,并按提示写入value 2.引用.复制出${__Random(1,99,gp)}放到需要引用的地方 3.请求成功后可通过debug sampler查看变量 ...