zoukankan      html  css  js  c++  java
  • HDU 5723 Abandoned country

    题目说每条边权值都不一样,说明最小生成树是唯一的,不存在最小期望这一说。

    然后就是先求出最小生成树,随便确定一个根节点,计算出每个点的子树有多少节点,记为c[x]。

    指向x的这条边被统计的次数为c[x]*(n-c[x])。然后基本就可以算出答案了。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    
    const int maxn = 100000 + 10;
    int T, n, m, f[maxn], c[maxn];
    bool flag[maxn];
    struct Edge { int u, v; LL cost; }e[10 * maxn], ee[maxn]; 
    vector<int>g[maxn];
    double fz, fm;
    
    int Find(int x) { if (x != f[x]) f[x] = Find(f[x]); return f[x]; }
    bool cmp(const Edge&a, const Edge&b) { return a.cost < b.cost; }
    
    void dfs(int x,int f)
    {
        flag[x] = 1; c[x] = 1;
        for (int i = 0; i < g[x].size(); i++)
        {
            int id = g[x][i]; if (flag[ee[id].v]) continue;
            dfs(ee[id].v,id); c[x] = c[x] + c[ee[id].v];
        }
        if (f != -1)
            fz = fz + 1.0*ee[f].cost*1.0*c[x] * 1.0* (n - c[x]);
    }
    
    int main()
    {
        scanf("%d", &T);
        while (T--) 
        {
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= m; i++)
                scanf("%d%d%lld", &e[i].u, &e[i].v, &e[i].cost);
            sort(e + 1, e + 1 + m, cmp);
            LL ans = 0;
            for (int i = 1; i <= n; i++) f[i] = i, g[i].clear();
            int sz = 0;
            for (int i = 1; i <= m; i++)
            {
                int fx = Find(e[i].u), fy = Find(e[i].v);
                if (fx != fy)
                {
                    f[fx] = fy, ans = ans + e[i].cost;
                    ee[sz].u = e[i].u, ee[sz].v = e[i].v, ee[sz].cost = e[i].cost;
                    g[e[i].u].push_back(sz++);
                    ee[sz].u = e[i].v, ee[sz].v = e[i].u, ee[sz].cost = e[i].cost;
                    g[e[i].v].push_back(sz++);
                }
            }
            memset(c, fz=0, sizeof c);
            memset(flag, fm=0, sizeof flag);  
            dfs(1, -1); 
            fm = 1.0*n*1.0*(n - 1) / 2.0;
            printf("%lld %.2lf
    ", ans, fz / fm);
        }
        return 0;
    }
  • 相关阅读:
    Java笔记(二十一) 动态代理
    Java笔记(二十) 注解
    Java笔记(十九) 反射
    Java笔记(十八)同步和协作工具类
    Java笔记(十七) 异步任务执行服务
    Spring使用笔记(四) 面向切面的Spring
    Spring使用笔记(三) 高级装配
    Java笔记(十六)并发容器
    Java笔记(十五) 并发包
    Java笔记(十四) 并发基础知识
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5693350.html
Copyright © 2011-2022 走看看