洛谷P3366 最小生成树

https://www.luogu.com.cn/problem/P3366

 /*
    1.把边从小到大排序
    2.将边从小到大遍历,确认是否能添加
    (1)如果边连接的两个点所在的点集(树相同,则跳过)
    (同一棵树上的两个点连接在一起会产生环,就不是树了)
    (2)点集不同则连接,之后可以进行相关的记录操作
*/
#include <bits/stdc++.h>
#define pii pair<int, int>
#define pb push_back
using namespace std;
int n, m;
vector<pii> to[5001];
int fa[5001];
struct lin{
    int u;
    int v;
    int val;
}li[200001];
//并查集查询
int ff(int x){
    if(fa[x]==0)
        fa[x] = x;
    if(fa[x]==x)return x;
    return fa[x] = ff(fa[x]);
}
bool cmp(lin a,lin b){
    return a.val < b.val;
}
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++) 
        scanf("%d%d%d", &li[i].u, &li[i].v, &li[i].val);
    sort(li + 1, li + 1 + m, cmp);//把边排序
    int ans = 0;
    int cnt = 0;
    for (int i = 1; i <= m;i++){
        int u = li[i].u;
        int v = li[i].v;
        int val = li[i].val;
        if(ff(u)==ff(v))//如果u,v是同一个分组跳过
            continue;
        fa[ff(v)] = ff(u);//合并u,v所在子树
        ans += val;//把边的权值加上
        cnt++;//把边数加上
    }
    if(cnt+1!=n)
        printf("orz");//假如边数+1不为点树,即最后没有构成一颗树
    else
        printf("%d", ans);//否则输出答案
}

点赞

发表回复