普及练习场 普及常见模板 【模板】最小生成树

题目链接:https://www.luogu.org/problemnew/show/P3366

题意理解

给出一个无向图,求出最小生成树。

这就是给用来验板子的

代码

#include <cstring>
#include <iostream>
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iomanip>
#include <vector>
#include <algorithm>

using namespace std;

/**
 * Kruskal算法求MST
 * 改自kuangbin大佬的模板,之前也有很多模板是用的他的,对这位前辈大佬表示感谢
 */
const int MAXN = 5010;//最大点数
const int MAXM = 200010;//最大边数
int F[MAXN];//并查集使用
struct Edge {
    int u, v, w;
} edge[MAXM];//存储边的信息,包括起点/终点/权值
int tol;//边数,加边前赋值为0
void add_edge(int u, int v, int w) {
    edge[tol].u = u;
    edge[tol].v = v;
    edge[tol++].w = w;
}

bool cmp(Edge a, Edge b) {//排序函数,讲边按照权值从小到大排序
    return a.w < b.w;
}

int find(int x) {
    if (F[x] == -1) {
        return x;
    } else {
        return F[x] = find(F[x]);
    }
}

long long Kruskal(int n) {//传入点数,返回最小生成树的权值,如果不连通返回-1
    memset(F, -1, sizeof(F));
    sort(edge, edge + tol, cmp);
    int cnt = 0;//计算加入的边数
    long long ans = 0;
    for (int i = 0; i < tol; i++) {
        int u = edge[i].u;
        int v = edge[i].v;
        int w = edge[i].w;
        int t1 = find(u);
        int t2 = find(v);
        if (t1 != t2) {
            ans += (long long) w;
            F[t1] = t2;
            cnt++;
        }
        if (cnt == n - 1) {
            break;
        }
    }
    //不连通
    if (cnt < n - 1) {
        return -1;
    } else {
        return ans;
    }
}
void read(int &x) {
    x = 0;
    int f = 1;
    char ch = getchar();
    while(ch > '9'||ch < '0') {
        if(ch == '-') {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        x = x * 10 + (int)(ch - 48);
        ch = getchar();
    }
    x = x * f;
}


int main() {
    tol = 0;
    int n, m;
    read(n);
    read(m);
    for(int i = 0; i < m; i++) {
        int x, y, z;
        read(x);
        read(y);
        read(z);
        add_edge(x, y, z);
    }
    long long res = Kruskal(n);
    if(res != -1L) {
        cout << res;
    } else {
        cout << "orz";
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值