【最小生成树之Kruskal算法】

看完之后推荐再看一看【最小生成树之Prim算法】-C++

定义:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。最小生成树可以用kruskal(克鲁斯卡尔)算法或Prim(普里姆)算法求出。 。
​在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集(即)且为无循环图,使得

的 w(T) 最小,则此 T 为 G 的最小生成树。

最小生成树其实是最小权重生成树的简称。

许多应用问题都是一个求无向连通图的最小生成树问题。例如:要在n个城市之间铺设光缆,主要目标是要使这 n 个城市的任意两个之间都可以通信,但铺设光缆的费用很高,且各个城市之间铺设光缆的费用不同;另一个目标是要使铺设光缆的总费用最低。这就需要找到带权的最小生成树。

这一章主要介绍Kruskal算法。

Kruskal算法的时间复杂度:O(m*log(n))(点数n边数m)

主要思路:

输入之后对边权值进行排序,然后按边权值从小到大进行合并(merge)操作,如果操作成功(被合并的两个点不在一棵树上),则把这两个顶点的边权值加入总数,最后输出total即可。
主要使用:

“并查集。”

洛谷P3366【模板】最小生成树
这道题我第一次是用Kruskal来写的,具体思路再讲解一下。
首先把get和merge函数写好,为了方便,我把merge写成了bool类型:如果成功合并(要求合并的两个顶点不在一棵树上)就返回true。
然后是最正常的运用结构体进行循环读入,读入完成之后写cmp排序函数按边权值从小到大进行排序。
接下来才和并查集扯上关系,所以要重新定义fa数组,然后进行初始化;

核心代码

	int cnt=0;
    int total=0;
    for(int i=1;i<=p;i++)//p为边数
    {
        if(merge(mp[i].u,mp[i].v))
        {
            cnt++;
            total+=mp[i].w;
            if(cnt==p-1) break;
        }
    }

这段代码主要是为了统计权值和。把权值从最小到最大跑一遍,如果能够合并就合并然后加进total即可。然后就没什么难的了emm。
下面贴代码;

参考代码:

#include
using namespace std;
struct noded
{
    int u,v;
    int w;
    noded(){}
    noded(int uu,int vv,int ww)
    {
        u=uu,v=vv,w=ww;
    }
}mp[200010];
bool cmp(noded x,noded y)
{
    return x.w>n>>p;
    for(int i=1;i<=p;i++)
    {
        cin>>mp[i].u>>mp[i].v>>mp[i].w;
    }
    sort(mp+1,mp+1+p,cmp);
    //for(int i=1;i<=k;i++)
    //{
    //  cout<

ov.

转载于:https://www.cnblogs.com/moyujiang/p/11167775.html

你可能感兴趣的:(【最小生成树之Kruskal算法】)