• HDU 2376 Average distance


    题目链接:HDU 2376 Average distance

    题目大意:
    计算一棵树中任意两点之间的距离的平均值。

    题解:
    如果暴力枚举两点再求距离是显然会超时的。

    转换一下思路,我们可以对每条边,求所有可能的路径经过此边的次数:设这条边两端的点数分别为(a)(b),那么这条边被经过的次数就是(a imes b),它对总的距离和的贡献就是(a imes b imes edge[i].len),我们把所有边的贡献求总和,再除以总路径数(frac{n imes (n-1)}{2}),即为最后所求。

    每条边两端的点数的计算,实际上是可以用一次(dfs)解决的。任取一点为根,在(dfs)的过程中,对每个点(k)记录其子树包含的点数(包括其自身),设点数为(siz[k]),则(k)的父亲一侧的点数即为(n-siz[k])

    #include <cstring>
    #include <iomanip>
    #include <iostream>
    using namespace std;
    
    int siz[10010], n, t, cnt, head[10010];
    long long ans;
    struct Edge {
        int v, len, next;
    } edge[20010];
    
    void addEdge(int u, int v, int w) {
        edge[++cnt].v = v;
        edge[cnt].len = w;
        edge[cnt].next = head[u];
        head[u] = cnt;
    }
    
    void dfs(int u, int pre) {
        siz[u] = 1;
        for (int i = head[u]; ~i; i = edge[i].next) {
            int v = edge[i].v;
            if (v == pre) {
                continue;
            }
            dfs(v, u);
            siz[u] += siz[v];
            ans += 1ll * siz[v] * (n - siz[v]) * edge[i].len;
        }
    }
    
    int main() {
        cin >> t;
        while (t--) {
            cnt = 0;
            memset(head, -1, sizeof(head));
            cin >> n;
            for (int i = 1, a, b, d; i < n; ++i) {
                cin >> a >> b >> d;
                addEdge(a, b, d);
                addEdge(b, a, d);
            }
            ans = 0;
            dfs(0, -1);
            cout << fixed << setprecision(6) << (double)ans / (n * (n - 1) / 2) << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    内部类概述和访问特点
    权限修饰符 权限
    抽象类和接口作为返回值类型的问题
    抽象类和接口作为形参问题
    jdbc:java数据库连接
    类与类、类与接口、接口与接口的关系
    接口
    抽象类
    多态
    继承中构造方法的关系
  • 原文地址:https://www.cnblogs.com/IzumiSagiri/p/15059662.html
Copyright © 2020-2023  润新知