zoukankan      html  css  js  c++  java
  • Codeforces 437D The Child and Zoo

    这个题还是很好的

    有几个套路

    先是我们看到题目中让我们处理点权,但是我们发现并不好处理

    所以就先化点为边 (套路1)

    把每一条边的边权视作边所连接的两个点的(min)

    然后我们看到这个题有路径的问题,就先还是要较大的

    可以比较显然地想到最大生成树 (套路2)

    (Kruskal)中改一下排序方式就行了

    然后我们看到不是生成树上的边都我们在考虑走的时候都不会考虑

    考虑每一个树边的贡献

    连接两个联通块的时候

    这一条边会产生(val[edge]* size[x]* size[y])的贡献 (套路3)

    然后就是并查集完事

    CODE:

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm {
    inline int read() {
        int res = 0, f = 1;
        char k;
        while (!isdigit(k = getchar())) {
            if (k == '-')
                f = -1;
        }
        while (isdigit(k)) {
            res = res * 10 + k - '0';
            k = getchar();
        }
        return res * f;
    }
    inline int max(int x, int y) { return x > y ? x : y; }
    inline int min(int x, int y) { return x < y ? x : y; }
    inline void swap(int &x, int &y) {
        int z = x;
        x = y;
        y = z;
        return;
    }
    const int N = 1e5 + 10;
    const int M = 1e6 + 10;
    struct node {
        int from, to, dis;
        bool operator<(const node &x) { return dis > x.dis; }
    } e[M];
    int n, m, val[N], sz[N], cnt, tot, fa[N];
    inline void add(int u, int v, int w) {
        e[++cnt].dis = w;
        e[cnt].from = u;
        e[cnt].to = v;
        return;
    }
    inline int find(int x) { return fa[x] == x ? fa[x] : fa[x] = find(fa[x]); }
    int u, v, w, ans;
    signed main() {
        n = read();
        m = read();
        for (int i = 1; i <= n; ++i) fa[i] = i, sz[i] = 1;
        for (int i = 1; i <= n; ++i) val[i] = read();
        for (int i = 1; i <= m; ++i) u = read(), v = read(), add(u, v, min(val[u], val[v]));
        sort(e + 1, e + m + 1);
        for (int i = 1; i <= m; ++i) {
            int x = find(e[i].from), y = find(e[i].to);
            if (x == y)
                continue;
            fa[x] = y;
            tot++;
            ans += sz[x] * sz[y] * e[i].dis;
            sz[y] += sz[x];
            if (tot == n - 1)
                break;
        }
        ans *= 2;
        double x = n * (n - 1);
        printf("%.8lf", (double)ans / x);
        return 0;
    }
    }  // namespace yspm
    signed main() {
        yspm::main();
        return 0;
    }
    
  • 相关阅读:
    软硬链接
    查看文件内容
    cp+mv
    cd+rm+pwd
    ls+tree
    绝对路径和相对路径
    Linux目录结构
    修改hostname
    java. util. concurrent. atomic
    git
  • 原文地址:https://www.cnblogs.com/yspm/p/12256494.html
Copyright © 2011-2022 走看看