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

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

文章目录


前言

树:同时满足极小连通图与极大无环图
支撑树:能够覆盖图中每一个顶点的树
最小支撑树:有权网络中满足各边权值之和最小的支撑树

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


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

(1)思路

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

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

(2)代码实现

#include<bits/stdc++.h>#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<<Prim()<<endl;}

二、kruskal算法(合木成林)

(1)思路

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

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

(2)代码实现

#include <bits/stdc++.h>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 <e; i++){   //进行初始化         parent[i] = i;//先保证不同     	}        for (int i = 0; i < e; i++){               cin>>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/

你可能感兴趣的文章
SQL 查询强化 - 数据准备
查看>>
SQL 强化练习 (四)
查看>>
SQL 强化练习 (八)
查看>>
Excel 拼接为 SQL 并打包 exe
查看>>
Pandas数据分析从放弃到入门
查看>>
Matplotlib绘制漫威英雄战力图,带你飞起来!
查看>>
机器学习是什么
查看>>
《小王子》里一些后知后觉的道理
查看>>
《自私的基因》总结
查看>>
《山海经》总结
查看>>
《非暴力沟通》总结
查看>>
《你当像鸟飞往你的山》总结
查看>>
《我是猫》总结
查看>>
《抗糖化书》总结
查看>>
apache虚拟主机配置
查看>>
光盘作为yum源
查看>>
PHP 正则表达式资料
查看>>
PHP官方网站及PHP手册
查看>>
mcrypt加密以及解密过程
查看>>
mysql连续聚合
查看>>