[洛谷] P3366 【模板】最小生成树 --- Kruskal

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz

输入输出格式

输入格式:
第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)

接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi

输出格式:
输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz

输入输出样例

输入样例#1:
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出样例#1:
7
1.Kruskal算法简介
Kruskal算法一般称作克鲁斯卡尔算法。克鲁斯卡尔算法是一种用来寻找最小生成树的算法。在剩下的所有未选取的边中,找最小边,如果和已选取的边构成回路,则放弃,选取次小边。
2.Kruskal算法思想
先构造一个只含 n 个顶点、而边集为空的子图,把子图中各个顶点看成各棵树上的根结点,之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,即把两棵树合成一棵树,反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直到森林中只有一棵树,也即子图中含有 n-1 条边为止。
  时间复杂度为为O(e^2), 使用并查集优化后复杂度为 O(eloge),与网中的边数有关,适用于求边稀疏的网的最小生成树。
3.Kruskal算法解题过程
首先我们需要解决一个问题,不能构成回路,这时,我们可以先使用并查集的思想,先把每条边存为独立的根,然后,寻找最短边权时,我们可将已经找过的边合并到集内,防止构成回路,选择其他的次小边。

2259.png

接着就是Kruskal处理核心,我们需要先将边进行排序,这样有利于后面选择最小边。
循环0-n次 且 i < n && nEdge != m - 1,为什么要nEdge != m - 1呢?
这个意思就表达了这个图是不连通的,也同样等价于不存在最小生成树。
接着,我们可以查找这两边的根,如果他们的根节点都不一样,就表示能够增加这个边权,它既是最小的,并且也不会构成回路。然后声明一个记住最小边权变量,最后输出既完成本题目。
下面是具体的代码实现

#include <cstdio>
#include <cstdlib>
#define MAXN 200000 + 10//对于100%的数据
using namespace std;

int par[MAXN], Rank[MAXN];//并查集 rank
typedef struct {
    int a, b, price;
}Node;//结构体储存
Node a[MAXN];

int cmp(const void*a, const void *b) {
    return ((Node*)a)->price - ((Node*)b)->price;//用于比较边权
}
void Init(int n) {
    for (int i = 0; i < n; i++) {
        Rank[i] = 0;
        par[i] = i;
    }
}

int find(int x) {
    int root = x;
    while (root != par[root]) root = par[root];
    while (x != root) {
        int t = par[x];
        par[x] = root;
        x = t;
    }
    return root;
}

void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (Rank[x] < Rank[y]) {
        par[x] = y;
    }
    else {
        par[y] = x;
        if (Rank[x] == Rank[y]) Rank[x]++;
    }
}
//n为边的数量,m为村庄的数量
int Kruskal(int n, int m) {
    int nEdge = 0, res = 0;
    //将边按照权值从小到大排序
    qsort(a, n, sizeof(a[0]), cmp);
    for (int i = 0; i < n && nEdge != m - 1; i++) {
        //判断当前这条边的两个端点是否属于同一棵树
        if (find(a[i].a) != find(a[i].b)) {
            unite(a[i].a, a[i].b);
            res += a[i].price;
            nEdge++;
        }
    }
    //如果加入边的数量小于m - 1,则表明该无向图不连通,等价于不存在最小生成树
    if (nEdge < m - 1) res = -1;
    return res;
}
int main() {
    int n, m, ans;
    scanf("%d%d", &n, &m);
    Init(n);
    for (int i = 0; i < m; i++) {
        scanf("%d%d%d", &a[i].a, &a[i].b, &a[i].price);
        //将村庄编号变为0~m-1(这个仅仅只是个人习惯,并非必要的)
        a[i].a--;
        a[i].b--;
    }
    int rets = Kruskal(m, n);//计算最小生成树
    //输出结果
    if (rets == -1)
        printf("orz");
    else printf("%d", rets);
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容

  • 第一章 绪论 什么是数据结构? 数据结构的定义:数据结构是相互之间存在一种或多种特定关系的数据元素的集合。 第二章...
    SeanCheney阅读 5,771评论 0 19
  • 1 序 2016年6月25日夜,帝都,天下着大雨,拖着行李箱和同学在校门口照了最后一张合照,搬离寝室打车去了提前租...
    RichardJieChen阅读 5,096评论 0 12
  • 整理自《数据结构高分笔记》 1、普里姆算法 算法思想普利姆算法的基本思想如下:从图中任意取出一个顶点,把它当成一棵...
    文哥的学习日记阅读 6,639评论 0 2
  • 草莓、圣女果 应邀着干红的孤独 就着钢琴曲《罪孽》的优美旋律 在这月明星稀的黑夜中 肆无忌惮地邂逅着、诠释着...
    格桑之恋阅读 314评论 5 6
  • 吃早点,把车停在了门口小径的一侧。边走边看到一辆红色电动三轮车停在了早点店的门口,正门口,从车上下来了一位红衣大妈...
    金金心阅读 125评论 0 0