经典的最小生成树例子,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的更多相关文章

  1. 算法起步之Kruskal算法

    原文:算法起步之Kruskal算法 说完并查集我们接着再来看这个算法,趁热打铁嘛.什么是最小生成树呢,很形象的一个形容就是铺自来水管道,一个村庄有很多的农舍,其实这个村庄我们可以看成一个图,而农舍就是 ...

  2. 无向带权图的最小生成树算法——Prim及Kruskal算法思路

    边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以 ...

  3. [数据结构]最小生成树算法Prim和Kruskal算法

    最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树.  例如,对于如上图G4所示的连通网可以有多棵权值总 ...

  4. 最小生成树(MST)Prim算法和Kruskal算法

    刚学完最小生成树,赶紧写写学习的心得(其实是怕我自己忘了) 最小生成树概念:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边. 就是说 ...

  5. ZOJ 1542 POJ 1861 Network 网络 最小生成树,求最长边,Kruskal算法

    题目连接:problemId=542" target="_blank">ZOJ 1542 POJ 1861 Network 网络 Network Time Limi ...

  6. 算法(图论)——最小生成树及其题目应用(prim和Kruskal算法实现)

    题目 n个村庄间架设通信线路,每个村庄间的距离不同,如何架设最节省开销? Kruskal算法 特点 适用于稀疏图,时间复杂度 是nlogn的. 核心思想 从小到大选取不会产生环的边. 代码实现 代码中 ...

  7. 算法笔记_066:Kruskal算法详解(Java)

    目录 1 问题描述 2 解决方案 2.1 构造最小生成树示例 2.2 伪码及时间效率分析 2.3 具体编码(最佳时间效率)   1 问题描述 何为Kruskal算法? 该算法功能:求取加权连通图的最小 ...

  8. 算法8-4:Kruskal算法

    Kruskal算法用于计算一个图的最小生成树.这个算法的过程例如以下: 依照边的权重从小到达进行排序 依次将每条边添加到最小生成树中,除非这条边会造成回路 实现思路 第一个步骤须要对边进行排序,排序方 ...

  9. 最小生成树(prime算法 & kruskal算法)和 最短路径算法(floyd算法 & dijkstra算法)

    一.主要内容: 介绍图论中两大经典问题:最小生成树问题以及最短路径问题,以及给出解决每个问题的两种不同算法. 其中最小生成树问题可参考以下题目: 题目1012:畅通工程 http://ac.jobdu ...

随机推荐

  1. WebGL简易教程(八):三维场景交互

    目录 1. 概述 2. 实例 2.1. 重绘刷新 2.2. 鼠标事件调整参数 3. 结果 4. 参考 1. 概述 在上一篇教程<WebGL简易教程(七):绘制一个矩形体>中,通过一个绘制矩 ...

  2. Java 学习笔记之 线程isInterrupted方法

    线程isInterrupted方法: isInterrupted()是Thread对象的方法,测试线程是否已经中断. public class ThreadRunMain { public stati ...

  3. laravel 5.5 运行在 php7.0 报错 Symfony\Component\Translation\Translator.php FatalThrowableErrorParse error: syntax error, unexpected '?', expecting variable (T_VARIABLE)

    问题描述 报错原因是 php-cli 版本是 7.1.x,运行 composer create-project ... 命令时安装的依赖包会自动适配到当前 php 版本 7.1.x.如果 php-fp ...

  4. netty源码解解析(4.0)-24 ByteBuf基于内存池的内存管理

    io.netty.buffer.PooledByteBuf<T>使用内存池中的一块内存作为自己的数据内存,这个块内存是PoolChunk<T>的一部分.PooledByteBu ...

  5. python编程基础之一

    编译:将全部代码转成二进制可执行文件 速度快, c,c++等 解释:一行一行的将代码解释 速度慢 python,php等 python简介:Guido van Rossum 1989年 常用的pyth ...

  6. Qt+VC2010+glew环境安装配置

    Qt的源码及预编译安装包在 Qt Archive下载,http://download.qt.io/archive/qt/, 目前最新的是Qt5,其中和Qt4不同的是,Qt5多了个QOpenGLWidg ...

  7. 代码审计-phpcms9任意文件读取

    漏洞文件: /phpcms/modules/content/down.php download函数 这个函数开始几行代码的作用和init函数中的几乎一样,都是从parse_str 解析传入的a_k参数 ...

  8. PHP array_slice

    1.函数的作用:返回数组中的部分区间的元素 2.函数的参数: @params  array  $array @params  int      $offset @params  int      $l ...

  9. opencv::形态学操作

    形态学操作 开操作- open 闭操作- close 形态学梯度- Morphological Gradient 顶帽 – top hat 黑帽 – black hat 开操作- open 先腐蚀后膨 ...

  10. 元素定位之css选择器(2)

    理论学习地址:https://www.runoob.com/cssref/css-selectors.html 定位思路: 先在单元素范围内选择查找id或name,定位不到的话往上查扩大范围 使用实例 ...