博客
关于我
数据结构——最小支撑树
阅读量:324 次
发布时间:2019-03-04

本文共 2984 字,大约阅读时间需要 9 分钟。

文章目录


前言

树:同时满足极小连通图与极大无环图

支撑树:能够覆盖图中每一个顶点的树
最小支撑树:有权网络中满足各边权值之和最小的支撑树

对于一幅图来说,存在的最小支撑树并不唯一。


一、Prim算法(由小树长成大树)

(1)思路

最小支撑树总是会采用联结每一割的最短跨越边。

用我的理解,就是不断拓展树的大小,用贪心思想在目前的最小支撑树的邻接点中搜索与树相连的边的最小权值,并将其加入树,之后更新树的邻接点的数据,直到树能够覆盖所有的顶点

适用于稠密图,O(|V|^2)

(2)代码实现

#include
#define MAX 0x3f3f3f;using namespace std;int sum;int n,m;//输入的N个点,和M条边int x,y,z;//输入变量int i,j,k;//循环变量int book[100];//用于记录这个点有没有被访问过int dis[100];//用于记录距离树的距离最短路程int maps[100][100];//用于记录所有边的关系int Prim(){ int min,minIndex; //初始化距离数组,默认先把离1点最近的找出来放好 for (i = 1; i <= n; i++) dis[i] = maps[1][i]; book[1]=1;//记录1已经被访问过了 for (i = 1; i <= n-1; i++){ //1已经访问过了,所以循环n-1次 min = MAX;//对于最小值赋值 for (j = 1; j <= n; j++){ //搜索树的邻接点与树相连的边的权最小值及该顶点 if(!book[j]&& dis[j] < min) { min = dis[j]; minIndex = j; } } //记录这个点已经被访问过了 book[minIndex] = 1; sum += dis[minIndex]; for (j = 1; j <= n; j++){ //刚刚树增加了一个点,现在把与这个点相连的边的数据更新为更小的权值 //通过这一步骤,我们可以在dis里面存入树的邻接点与树相连的边的权值 if(book[j] == 0 && maps[minIndex][j] < dis[j]) dis[j] = maps[minIndex][j]; } }}int main(){ cin>>n>>m;//---------------------------------------------------- //初始化maps,除了自己到自己是0其他都是边界值 for (i = 1; i <= n; i++){ for (j = 1; j <= n; j++){ if(i!=j){ maps[i][j] = MAX; } else maps[i][j] = 0; } } for (i = 1; i <= m; i++){ cin>>x>>y>>z;//输入的为无向图 maps[x][y] = z; maps[y][x] = z; }//---------------------------------------------------- cout<
<

二、kruskal算法(合木成林)

(1)思路

贪心思想,每次会在剩余的边中选出权值最小的边,从而构成一棵棵子树,最终合木成林,但对于边的选择却存在要求,边不能属于同一棵子树,否则就形成了环路,不符合树的要求,直至边数等于总顶点数减一,结束检索。

适用于稀疏图,O(|V|*log|V|)

(2)代码实现

#include 
using namespace std;struct Edge{ int u; int v; int w;};int parent[201];//---------------------------------------- bool cmp(Edge e1, Edge e2){ //对于结构体内部数据排序所需要 return e1.w < e2.w; }//---------------------------------------- int find(int x) { //递归求子树最终根节点 if (x == parent[x]) return x; return parent[x] = find(parent[x]);//更新每个点的最终根节点 }//---------------------------------------- int merge(int x, int y){ //判断是否属于同一棵子树 int a = find(x); int b = find(y); if (a != b) { parent[b] = a; return 1; } return 0;}int main(){ int n, e; while (cin >> n >> e){ Edge edge[e]; for (int i = 0; i
>edge[i].u>>edge[i].v>>edge[i].w; } sort(edge,edge+e,cmp); int cnt = 0, sum = 0;//cnt为树中的边数,sum为树中各边之和 for (int i = 0; i < e; i++){ if (merge(edge[i].u, edge[i].v)){ cnt++; sum += edge[i].w; } if (cnt == n - 1) break; } if (cnt == n - 1) cout << sum << endl; else cout <<"NO TREE"<< endl; } return 0;}

转载地址:http://zoah.baihongyu.com/

你可能感兴趣的文章
vscode 编辑python 如何格式化
查看>>
正则表达针对html(九)
查看>>
seo 回忆录百度基本概念(一)
查看>>
重新整理数据结构与算法(c#)—— 算法套路二分法[二十四]
查看>>
不一样的备忘录模式(设计模式十六)
查看>>
【golang-GUI开发】qt之signal和slot(一)
查看>>
kettle 执行 kjb 临时文件夹 /tmp permission denied 问题
查看>>
Markdown使用笔记
查看>>
「从零单排HBase 06」你必须知道的HBase最佳实践
查看>>
「从零单排canal 04」 启动模块deployer源码解析
查看>>
用ThreadLocal来优化下代码吧
查看>>
netcore中使用session
查看>>
Android 开发学习进程0.25 自定义控件
查看>>
多媒体文件格式全解说(下)--图片
查看>>
淘宝WAP版小BUG分析
查看>>
Java并发之ThreadPoolExecutor源码解析(三)
查看>>
TCP/IP网络编程之域名及网络地址
查看>>
Redis实现之对象(三)
查看>>
NodeJS+Express+MongoDB
查看>>
(五)c#Winform自定义控件-复选框-HZHControls
查看>>