数据结构-最小生成树 速通指南

数据结构-最小生成树 速通指南

文章目录

  • 数据结构-最小生成树 速通指南
    • 1.生成树与最小生成树介绍
    • 2.最小生成树算法一:Kruskal算法(克鲁斯卡尔算法)
    • 3.最小生成树算法二:Prim算法(普里姆算法)
    • 4.最小生成树相关练习

1.生成树与最小生成树介绍

树与图的一个重要区别就是树中不存在回环,而生成树就是把图中构成回环的部分去掉部分边以去掉回环,从而产生的树就叫做生成树。而每条边都有权值的时候,总权值之和最小的树就叫做最小生成树,而求其最小生成树的算法主要用到两种最小生成树算法。

2.最小生成树算法一:Kruskal算法(克鲁斯卡尔算法)

Kruskal是加边算法,其思路为把所有的边按权值升序排序,依次把边加到点图中,并判断是否形成回环,若形成回环则不加,不形成则加,直到边被加完或者最小生成树构造完成为止。比较适合用于边比较稀疏的图

其中涉及判断环路的部分需要并查集的知识,若不知道的可以先看看:数据结构-并查集 速通指南

数据结构-最小生成树 速通指南_第1张图片

K r u s k a l : { 1. 对 边 按 权 排 序 2. 按 权 值 从 小 到 大 加 边 , 加 了 后 是 否 构 成 回 环 ? { 1. 构 成 , 不 加 边 2. 不 构 成 , 加 边 3. 边 不 够 或 者 最 小 生 成 树 完 成 , 结 束 Kruskal: \begin{cases} 1.对边按权排序\\ 2.按权值从小到大加边,加了后是否构成回环?\begin{cases} 1.构成,不加边\\ 2.不构成,加边\\ \end{cases}\\ 3.边不够或者最小生成树完成,结束 \end{cases} Kruskal:1.2.{1.2.3.

#include
using namespace std;

vector<pair<int,pair<int,int> > > edge;
int pre[MAXN];
int weight;

int find(int x){//并查集 查
    if(pre[x] == x) return x;
    else return find(pre[x]);
}

void join(int x,int y){//并查集 并
    x = find(x),y = find(y);
    if(x != y) pre[x] = y;
}

int main(){
    for(int i = 0;i < MAXN;i++) pre[i] = i;//并查集前继数组的初始化
    
    sort(edge.begin(),edge.end(),[](pair<int,pair<int,int> > 						a,pair<int,pair<int,int> > b){return a.second.second < b.second.second});//对边排序
    
    int num = 0;//记录加入的边数
    for(int i = 0;i < edge.size();i++){
		if(find(edge[i].first) != find(edge[i].second.first){//如果根节点不同,则说明		  //不形成回路,则加入该边
             join(edge[i].first,edge[i].second.first);
             num++;//加入边数加一
             weight += edge[j].second.second;//最小权值累加
        }
        if(num >= pointnum - 1) break;//当加入边数为点数减一时说明最小生成树已经生成,则		结束循环
    }
           
    if(num >= pointnum - 1) cout << weight;//判断最小生成树是否生成成功,成功则输出最小	  //权值
    else cout << -1;//失败则输出-1
           
    return 0;
}


3.最小生成树算法二:Prim算法(普里姆算法)

Prim算法即加点的算法,利用的是蓝白点思想,所以其代码与同为蓝白点算法的迪杰斯特拉算法高度相似(几乎一模一样),最短路算法先挖个坑,以后填了再在这里加个超链接。其思想为,选取一个点,然后找到周围权值最小的边,并标记其点,下次从该点开始重复步骤。比较适合用于边稠密的图

数据结构-最小生成树 速通指南_第2张图片

#include
using namespace std;
const long long INF = 0x3f3f3f3f;
int mp[MAXN][MAXN];
bool book[MAXN];
int mindist[MAXN];
int sum;

int main(){
    //初始化
    for(int i = 0;i < MAXN;i++) mindist[i] = INF;
    mindist[1] = 0;
    book[1] = true;
    int num = 0;
    
    while(num++ < pointnum - 1){
        int m = INF,k = 0;
        for(int i = 1;i < MAXN;i++){//找到最短距离点
            if(mindist[i] < m){
                m = mindist[i];
                k = i;
            }
	    }
        sum += mindist[k];//最小权值累加
        book[k] = true;//标记
        for(int i = 1;i < MAXN;i++){//更新mindist
			if(!book[i] && mp[k][i] < mindist[i]){
                mindist[i] = mp[k][i];
            }
        }
    }
    
    for(int i = 1;i < MAXN;i++) if(mindist[i] == INF) cout << -1,return 0;//失败输出-1
    cout << sum;//成功输出最小权值
    return 0;
}

4.最小生成树相关练习

做到一个补一个~

你可能感兴趣的:(数据结构与算法,数据结构,算法)