最小生成树——Kruscal(克鲁斯卡尔算法)

一、核心思想

​ 将输入的数据由小到大进行排序,再使用并查集算法传送门)将每个点连接起来,同时求和。

​ 个人认为这个算法比较偏向暴力,有些题可能会超时。

二、例题 洛谷—P3366

题目地址:https://www.luogu.org/problemnew/show/P3366

这是一道非常好的克鲁斯卡尔算法的模板题。

题目描述

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

输入输出格式

输入格式:

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

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

输出格式:

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

输入输出样例

输入样例:

	4 5
	1 2 2
	1 3 2
	1 4 3
	2 3 4
	3 4 3

输出样例:

	7

AC代码:

这段是符合题意的改良代码,一开始我提交的时候没有做orz的输出,由于题的数据问题导致没有设计orz也过了😄😄😄。

#include<iostream>
#include<algorithm>
#include<cstdio>

using namespace std;
int root[500000];
int book[500000];
int n, m;
int ans;

struct node
{
    int be, en, dis;
}road[500000];

bool cmp( node a, node b)
{
    return a.dis < b.dis;
}

int findx( int a)
{

    if (a == root[a])
        return a;
    else
        return root[a] = findx(root[a]);
}

void mix( int a, int b)
{
    int fr = findx(a), lr = findx(b);
    if(fr != lr)
        root[b] = fr;
}

int kruscal()
{
    int sum = 0;
    int t1, t2;
    for( int i = 1; i <= m; i++)
    {
        t1 = findx(road[i].be);
        t2 = findx(road[i].en);
        if( t1 != t2)
        {
            sum += road[i].dis;
            ans++;
            mix(t1,t2);
        }
        if(ans == n-1)
            break;
    }
    return sum;
}

int main()
{
    int sum;
    
    cin >> n >> m;
    for( int i = 1; i <= n; i++)
        root[i] = i;
    for( int i = 1; i <= m; i++)
        scanf("%d%d%d", &road[i].be, &road[i].en, &road[i].dis);
    sort( road+1, road+m+1, cmp);	//对输入的数据进行排序
    sum = kruscal();
    if(ans == n-1)
        cout << sum << endl;
    else
        cout << "orz" << endl;
    return 0;
}

能力有限,有错误麻烦指出,万分感谢。

posted @ 2019-03-31 09:15  Trirabbits三兔  阅读(386)  评论(0编辑  收藏  举报