HDU

来源:互联网 发布:python批处理文件 编辑:程序博客网 时间:2024/06/05 09:09

题意:

给出n个点和m条边,每条边有一个权值,题目保证每条边的权值都不一样,求出一个权值最小生成树,并且求出任意选择n个点中的两点之间距离的权值的最小期望。

思路:

最小生成树没什么好说的,因为每条边权值不一样,所以可以保证求出的最小生成树一定只有一个解。按照求出的最小生成树建一棵树,所谓期望=任意两点之间的距离和/C(n,2),这样只要求出任意选择两个点的所有情况的距离和即可,dp一下。

代码:

#include <bits/stdc++.h>using namespace std;const int MAXN = 1e5 + 10;const int MAXM = 1e6 + 10;struct Edge {    int u, v, w;    bool operator < (const Edge &rhs) const {        return w < rhs.w;    }} e[MAXM];struct node {    int v, w;};int n, m;int pa[MAXN];vector <node> tree[MAXN];void init() {    for (int i = 1; i <= n; i++) {        pa[i] = i;        tree[i].clear();    }}int Find(int x) {    return x == pa[x] ? x : pa[x] = Find(pa[x]);}long long kruskal() {    init();    long long res = 0;    sort(e + 1, e + 1 + m);    for (int i = 1; i <= m; i++) {        int pu = Find(e[i].u), pv = Find(e[i].v);        if (pu != pv) {            pa[pu] = pv;            int u = e[i].u, v = e[i].v, w = e[i].w;            tree[u].push_back((node){v, w});            tree[v].push_back((node){u, w});            res += w;        }    }    return res;}int sum[MAXN];double expe = 0;int dfs(int u, int pre) {    sum[u] = 1;    int cnt = tree[u].size();    for (int i = 0; i < cnt; i++) {        int v = tree[u][i].v, w = tree[u][i].w;        if (v == pre) continue;        sum[u] += dfs(v, u);        expe += (double)sum[v] * (n - sum[v]) * w;    }    return sum[u];}int main() {    //freopen("in.txt", "r", stdin);    int T;    scanf("%d", &T);    while (T--) {        scanf("%d%d", &n, &m);        for (int i = 1; i <= m; i++)            scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);        printf("%I64d", kruskal());        expe = 0;        dfs(1, -1);        double tmp = (double)n * (n - 1) / 2.0;        printf(" %.2f\n", expe / tmp);    }    return 0;}

0 0
原创粉丝点击