经典的最小生成树例子,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. 漫谈 GOF 设计模式在 Spring 框架中的实现

    原文地址:梁桂钊的博客 博客地址:http://blog.720ui.com 欢迎关注公众号:「服务端思维」.一群同频者,一起成长,一起精进,打破认知的局限性. 漫谈 GOF 设计模式在 Spring ...

  2. hadoop之yarn详解(框架进阶篇)

    前面在hadoop之yarn详解(基础架构篇)这篇文章提到了yarn的重要组件有ResourceManager,NodeManager,ApplicationMaster等,以及yarn调度作业的运行 ...

  3. vs2019下载和更新速度非常慢的解决方案

    纵观全网,就两种解决方案 1.取消网络适配器里面的IPV6的给勾选[我试过,无效,但是有些网友说是有效果,也不知道是咋回事] 2.修改host.[本人亲测有效果,速度从5kb到5M左右,但是无法跑满宽 ...

  4. 如何在linux下编写一个简单的Shell脚本程序

    在了解了linux终端和其搭配的基本Shell(默认为bash)的基础下,我们就可以在终端中用vi/vim编辑器编写一个shell的脚本程序了 Shell既为一种命令解释解释工具,又是一种脚本编程语言 ...

  5. 一种Cortex-M内核中的精确延时方法

    本文介绍一种Cortex-M内核中的精确延时方法 前言 为什么要学习这种延时的方法? 很多时候我们跑操作系统,就一般会占用一个硬件定时器--SysTick,而我们一般操作系统的时钟节拍一般是设置100 ...

  6. 从输入URL到页面渲染完成 -戈多编程

    1.输入URL地址 2.浏览器根据域名查询IP地址 3.浏览器发送HTTP请求到web服务器 4.服务器返回一个永久重定向响应 5.浏览器会跟踪重定向地址 6.服务器处理请求 7.服务器返回一个HTM ...

  7. LeetCode_682-Baseball Game

    给定一个字符串列表,字符串包含整数,’+’,’D’,’C’,整数代表一个分数,’+’代表后两个有效分数的和,’D’代表后一个有效分数的两倍,’C’代表删除后一个有效的分数值,最后求所有有效分数的和.例 ...

  8. bugku 各种·绕过

    点开是一段PHP的代码,先来审计一波代码. 发现将uname和passwd用sha1进行了加密,那么我们只要绕过这个函数构造相等就可以了. 可以使这两个值sha1的值相等,但他们本身的值又不等.(想详 ...

  9. 机器学习中梯度下降法原理及用其解决线性回归问题的C语言实现

    本文讲梯度下降(Gradient Descent)前先看看利用梯度下降法进行监督学习(例如分类.回归等)的一般步骤: 1, 定义损失函数(Loss Function) 2, 信息流forward pr ...

  10. C# 委托 (一)—— 委托、 泛型委托与Lambda表达式

    C# 委托 (一)—— 委托. 泛型委托与Lambda表达式 2018年08月19日 20:46:47 wnvalentin 阅读数 2992   版权声明:此文乃博主之原创.鄙人才疏,望大侠斧正.此 ...