ACM_kruscal 计算最小生成树

算法作用

计算最小生成树
生成树: 将一个图的顶点不变, 通过去除一些边, 使它成为一棵树
最小生成树: 所有生成树中的边权和最小的生成树
比如下面图1的最小生成树是图2
这里写图片描述
图1
这里写图片描述
图2

时间复杂度

O(ElogE)E是边数

代码实现

#include <iostream>
#include <algorithm>
using namespace std;

const int N = 1e5 + 10;
const int M = 1e5 + 10;
int pa[N];

struct Edge {
    int from, to, cost;
    bool operator < (const Edge & rhs) const {
        return cost < rhs.cost;
    }
};

Edge oldEdge[N], newEdge[N];

int find(int x) {
    return x == pa[x] ? x : pa[x] = find(pa[x]);
}

void readData();

int main() {
    readDate();
    for(int i = 0; i < n; ++i)
        pa[i] = i;
    int cnt = 0;
    sort(oldEdge, olEdge + m);
    for(int i = 0; i < m; ++i) {
        int fx = find(oldEdge[i].from);
        int fy = find(oldEdge[i].to);
        if(fx == fy) continue;
        pa[fx] = fy;
        newEdge[cnt++] = oldEdge[i];
    }
}

其中oldEdge是老图, newEdge是新图, n是顶点数, m是边数, pa是用来实现并查集的父亲指向
代码的主体部分仅两个
1. sort的排序函数
2. find的并查集查找函数(包括后面的合并操作)
其中以前的图以边的方式存储在oldEdge中, 得到的新图的边同样以边的方式存在newEdge中, 如果想用邻接矩阵, 邻接表或者链式前向星等, 转化一下即可

算法拓展

某些看似和路径无关的可以转移过来, 看个人灵活性了吧

算法证明

算法的基本思想是: 从最小的边开始, 一直找, 不停的合并到新图中, 直到遍历所有边
证明: 反证法
设由Kruskal算法生成的T0序列为e1, e2, e3 … ev-1,假设其不是最小生成树。任意最小生成树T定义函数f(T):T0中不存在于T中边在T0的下标。设T1是使f(T)最大的变量,设f(T1)=k,即ek不存在于T1中,T1为树且ek不在T1中,所以由引理1得T1+ek必存在圈C,C上必有e,k ≠ek,e,k不在T0 中。现令T2 = T1 - e,k + ek,则T2也为生成树但由Kruskal算法可知ek是使e1, e2 … ek-1, ek无圈的权值最小的边,e1, e2 … ek-1, e,k是树的子图必无圈故e,k的权值必定小于ek,即T2的总权值不大于T1的权值,因T1是最小生成树,故必T2也是最小生成树,但f(T2)>k与k是f函数最大取值矛盾,故T0是最小生成树。

代码实现的具体过程及思路

主要就两个过程
先sort一下, 然后不断的选最小的边来进行扩展, 知道用完所有的边
要点无非两个:
1. sort, 使用stl中的sort即可(用的是归并排序, 时间复杂度是ElogE)
2. 并查集算法, 这个在我以前写的一篇博客中详细介绍了这种算法, 链接如下
http://blog.csdn.net/fkjslee/article/details/48809903

复杂度证明

第一个复杂度来自sort, stl中的归并排序, 复杂度ElogE, 没什么好解释的
第二个复杂度来自并查集, 并查集的一次查找的复杂度是反阿克曼函数, 近似等于O(1), 一个会查找E* 2次, 所以复杂度是O(E)
所以总的复杂度是O(ElogE)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值