经典的最小生成树例子,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. Kafka 学习笔记之 Kafka0.11之producer/consumer(Scala)

    Kafka0.11之producer/consumer(Scala): KafkaConsumer: import java.util.Properties import org.apache.kaf ...

  2. 排坑日记之批量从库IO进程停止

    早上刚睁眼,看到了一堆数据库告警的短信,其中一个内容如下: Problem started at 05:02:58 on 2019.10.12 Problem name: Slave is stopp ...

  3. python常用算法学习(3)

    1,什么是算法的时间和空间复杂度 算法(Algorithm)是指用来操作数据,解决程序问题的一组方法,对于同一个问题,使用不同的算法,也许最终得到的结果是一样的,但是在过程中消耗的资源和时间却会有很大 ...

  4. python编程基础之四

    注释: 单行注释 #    例: # age = 10 多行注释  三引号“”“  ”“”,‘‘‘ ’’’ 例:“““  age = 10   ””” 只要注释较难的代码, 注释比例大概占总数的30% ...

  5. RF中的if判断

    关键字run keyword if 格式如下: Run Keyword If  判断条件   其他关键字 ...      ELSE IF    判断条件   其他关键字 ...    ELSE   ...

  6. C 自删除技术---批处理方式

    #include<stdio.h> #include<windows.h>#pragma comment(linker, "/subsystem:\"win ...

  7. 机器学习实战3:逻辑logistic回归+在线学习+病马实例

    本文介绍logistic回归,和改进算法随机logistic回归,及一个病马是否可以治愈的案例.例子中涉及了数据清洗工作,缺失值的处理. 一 引言 1 sigmoid函数,这个非线性函数十分重要,f( ...

  8. [Luogu3069][USACO13JAN]牛的阵容Cow Lineup

    题目描述 Farmer John's N cows (1 <= N <= 100,000) are lined up in a row. Each cow is identified by ...

  9. [Luogu2455] [SDOI2006]线性方程组

    题目描述 已知n元线性一次方程组. 其中:n<=50, 系数是[b][color=red]整数<=100(有负数),bi的值都是整数且<300(有负数)(特别感谢U14968 mmq ...

  10. [TYVJ2340] 送礼物 - 双向搜索

    题目限制 时间限制 内存限制 评测方式 题目来源 1000ms 131072KiB 标准比较器 Local 题目描述 作为惩罚,GY被遣送去帮助某神牛给女生送礼物(GY:貌似是个好差事)但是在GY看到 ...