算法导论——最小生成树

简介:   对于一个连通图来说,我们可以去掉其中一些边依然保持其连通的性质,在这些图中存在一个或多个图,他们的路径总和是最小的,这样的图必然是树。因为,如果说图中存在环,则去掉环的一条边依然可以保证连通性,这与总路径和最小是矛盾的。

  对于一个连通图来说,我们可以去掉其中一些边依然保持其连通的性质,在这些图中存在一个或多个图,他们的路径总和是最小的,这样的图必然是树。因为,如果说图中存在环,则去掉环的一条边依然可以保证连通性,这与总路径和最小是矛盾的。这样的图被称为最下生成树。城市间铺设电路就可以利用最小生成树来进行规划。

如图所示的黑色路径构成了最小生成树,去掉bc并加入ah也是一棵最小生成树,可见一个图的最小生成树并不一定是唯一的。

  最小生成树可以使用安全边的策略进行生成:假设集合A是最小生成树的子集,我们可以找到一条边加入到A中,依然保持A是最小生成树的子集,这样的边就被称为安全边。为了寻找安全边,我们定义下方黑色部分ab与de边构成了集合A,(A,V-A)称为G的一个切割。如果一条边(v,u)一个端点属于A而另一个端点属于V-A,则称它为横跨切割(A,V-A)。在横跨切割的边中,可以找到一条或多条权重最小的边,该边称为轻量级边,轻量级边即是安全边。因为A一定要与V-A部分产生连接,这就必须要通过横跨切割的边,而轻量级边是其中最短的,所以必定属于最小生成树。下图所示ah bj bc cd df ef为横跨切割的边,其中cd为轻量级边。为了寻找轻量级边,有两种基于贪心策略的算法。

Kruskal算法

  Kruskal算法的思想是,寻找连接森林中两棵不同树的边里面的最短边作为安全边加入集合A。可以使用不相交集合来维护这样的结构,对每个结点建立一棵树。通过FIND-SET来返回结点属于哪棵树,有边加入集合A时合并u和v所在的树。时间复杂度可表示为O(ElgV)。

图中所示为各边按照长度顺序不断遍历检查是否要加入到集合A中,直到遍历完所有的边结束。

#include<stdio.h>
#include<vector>
#include <algorithm>
using namespace std;
#define SIZE 10

class Node{
public:
    int rank;
    Node *p;
};

class Road{
public:
    int u;
    int v;
    int weight;
};

int G[SIZE][SIZE];//邻接矩阵,参数初始化略
Node nodes[SIZE];

void makeSet(Node x){
    x.p = &x;
    x.rank = 0;
}

void Union(Node x,Node y){
    if(x.rank > y.rank)
        y.p = &x;
    else{
        x.p = &y;
        if(x.rank == y.rank)
            y.rank++;
    }
}

Node* findSet(Node x){
    if(x.p != &x)
        x.p = findSet(*x.p);
    return x.p;
}

bool com (Road a,Road b) {
    return (a.weight<b.weight); //升序排列
}

vector<Road> MSTKruskal(){
    vector<Road> A;
    int i,j;
    vector<Road> roads;
    for(i = 0; i < SIZE; i++){
        nodes[i] = *new Node();
        makeSet(nodes[i]);//每棵树包含一个结点
    }
    for(i = 0; i < SIZE; i++){
        for(j = i + 1; j < SIZE; j++){
            if(G[i][j] != 0){
                Road road = *new Road();
                road.u = i;
                road.v = j;
                road.weight = G[i][j];
                roads.push_back(road);
            }                
        }
    }
    sort(roads.begin(),roads.end(),com);//对所有路径进行降序排列
    for(i = 0; i < roads.size(); i++){
        Road road = roads[i];
        if(findSet(nodes[road.u]) != findSet(nodes[road.v])){
            A.push_back(road);
            Union(nodes[road.u],nodes[road.v]);
        }
    }
    return A;
}

Prim算法

  Prim算法的思路是从根结点开始加入集合A,不断寻找A与V-A相连边中最短的,即横跨(A,V-A)的轻量级边。可以将V-A到A距离的最小值存储到优先队列Q中来减少每次遍历寻找最短边的时间。优先队列可以通过最小二叉堆或者斐波那契堆来实现,前者的渐进时间为O(ElgV)后者改进为O(E+VlgV)

#include<stdio.h>
#include<vector>
using namespace std;
#define SIZE 10
#define INFI 10000

class Road{
public:
    int u;
    int v;
    int weight;
};

int G[SIZE][SIZE];//邻接矩阵,参数初始化略

vector<Road> MSTPrim(int root){
    vector<Road> A;
    int i;
    Road roads[SIZE];//记录到达A的最短路径
    for(i = 0; i < SIZE; i++){
        roads[i] = *new Road();
        if(G[root][i] != 0){
            roads[i].u = root;
            roads[i].v = i;
            roads[i].weight = G[root][i];
        }
        else
            roads[i].weight = INFI;
    }
    while(A.size() != SIZE - 1){
        int min = 0;
        for(i = 1; i < SIZE; i++){
            if(roads[i].weight < roads[min].weight && roads[i].weight > 0)
                min = i;//寻找最短的路径
        }
        A.push_back(roads[min]);
        roads[min].weight = -1;//表示该点已在A中
        for(i = 0; i < SIZE; i++){
            if(G[min][i] < roads[i].weight)
                roads[i].weight = G[min][i];//更新到达A的最短长度
        }
    }
    return A;
}

 

个人GitHub地址: https://github.com/GrayWind33
相关文章
|
6月前
|
算法 索引
class061 最小生成树【算法】
class061 最小生成树【算法】
83 0
|
算法
最小生成树算法:Prim算法
在图论中,最小生成树(Minimum Spanning Tree,简称MST)是一种常用的算法问题。最小生成树是指在一个加权连通图中选取边的子集,使得所有顶点都被覆盖,并且边的总权值最小。
268 0
|
1月前
|
算法 决策智能
基于prim算法求出网络最小生成树实现网络社团划分和规划
该程序使用MATLAB 2022a版实现路线规划,通过排序节点权值并运用Prim算法生成最小生成树完成网络规划。程序基于TSP问题,采用遗传算法与粒子群优化算法进行路径优化。遗传算法通过编码、选择、交叉及变异操作迭代寻优;粒子群优化算法则通过模拟鸟群觅食行为,更新粒子速度和位置以寻找最优解。
|
4月前
|
存储 传感器 算法
|
5月前
|
算法 Java
Java数据结构与算法:贪心算法之最小生成树
Java数据结构与算法:贪心算法之最小生成树
|
5月前
|
算法 C语言
数据结构与算法——最小生成树问题(什么是最小生成树、Prim算法、Kruskal算法)
数据结构与算法——最小生成树问题(什么是最小生成树、Prim算法、Kruskal算法)
34 0
|
6月前
|
存储 机器学习/深度学习 算法
上机实验三 图的最小生成树算法设计 西安石油大学数据结构
上机实验三 图的最小生成树算法设计 西安石油大学数据结构
86 1
|
6月前
|
人工智能 算法
一些算法的复习(最短路径、最小生成树、dp)
一些算法的复习(最短路径、最小生成树、dp)
|
6月前
|
算法
最小生成树算法
最小生成树算法
|
6月前
|
算法 Java C++
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-6 算法训练 安慰奶牛 最小生成树
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-6 算法训练 安慰奶牛 最小生成树
47 0