Codeforces Round #529 (Div. 3) F. Make It Connected(最小生成树)

在这里插入图片描述

AC

  • 最小生成树,建边的时候不需要 N 2 {N^2} ,首先N个点需要N-1条边,每个顶点都会用到,也会有一些顶点重复。我们让重复的点为权值最小的点,就可以保证生成树最小
  • 将特殊边加到边集里,跑一边Kruskal
#include <bits/stdc++.h>
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define REP(i, n) for (int i = 1; i <= (n); ++i)
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define N 200006
#define LL  long long
using namespace std;
struct ac{
    LL u, v, d;
}g[N*2];
LL a[N];
int fa[N];
int find(int x) {
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    int n, m;
    while (scanf("%d %d", &n, &m) != EOF) {
        int pos = 1;
        REP (i, n) {
            scanf("%lld", &a[i]);
            if (a[i] < a[pos])  pos = i;
        }
        int len = 0;
        REP (i, n) {
            if (i == pos)   continue;
            g[len].u = pos;
            g[len].v = i;
            g[len].d = a[pos] + a[i];
            len++;
        }
        rep (i, m) {
            scanf("%lld %lld %lld", &g[len].u, &g[len].v, &g[len].d);
            ++len;
        }
        sort(g, g + len, [&](const ac &x, const ac &y){
            return x.d < y.d;
        });
        REP (i, n)  fa[i] = i;
        LL u, v, d, ans = 0, cnt = 0;
        rep (i, len) {
            u = g[i].u;
            v = g[i].v;
            d = g[i].d;
            if (find(u) != find(v)) {
                fa[find(u)] = find(v);
                ans += d;
                if (++cnt == n-1)   break;
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/henuyh/article/details/85320095