//目录

HDU 5723 最小生成树上的期望

题意:求最小生成树,和任意两个点之间距离的期望

官方题解:

最后求两遍点的积的时候,还是要判断父子关系。

注意 long long

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const int maxn = 100000+5;
int father[maxn];


int Find_Set(int x) {
    if(x!=father[x])
        father[x] = Find_Set(father[x]);
    return father[x];
}

struct Edge {
    int u,v,d;
    bool operator < (const Edge & rhs) const {
        return d < rhs.d;
    }
}edges[1000000+5];

struct o {
    int v,d;
};

vector <o> G[maxn];
int sum[maxn];
bool vis[maxn];
int ff[maxn];

int x;
void dfs(int r,int f) {
    if(vis[r]) return ;
    sum[r] = 1;
    vis[r] = true;
    for(int i=0;i<G[r].size();i++)
    {
        int v = G[r][i].v;
        if(v!=f) {
            ff[v] = r;
            dfs(v,r);
            sum[r] +=sum[v];
        }
    }
}

vector<Edge> minans;

int main()
{
    //freopen("in.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--) {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<=n;i++)
            father[i] = i;

        for(int i=0;i<=n;i++) {
            G[i].clear();
        }


        minans.clear();
        memset(sum,0,sizeof(sum));
        memset(vis,0,sizeof(vis));
        x = 0;

        for(int i=0;i<m;i++)
            scanf("%d%d%d",&edges[i].u,&edges[i].v,&edges[i].d);

        sort(edges,edges+m);

        LL ans = 0;
        for(int i=0;i<m;i++) {
            int u = edges[i].u;
            int v = edges[i].v;
            int d = edges[i].d;
            int fx = Find_Set(u);
            int fy = Find_Set(v);
            if(fx!=fy)
            {
                G[u].push_back((o){v,edges[i].d});
                G[v].push_back((o){u,edges[i].d});
                minans.push_back((Edge){u,v,d});
                father[fy] = fx;
                ans +=edges[i].d;
            }
        }

        dfs(1,-1);

        LL x = 0;
        for(int i=0;i<minans.size();i++) {
            int u,v,d;
            u = minans[i].u;
            v = minans[i].v;
            d = minans[i].d;

            if(ff[u]==v) {
                x +=(LL)sum[u]*(LL)((LL)n-sum[u])*d;
            }
            else if(ff[v]==u) {
                x +=(LL)sum[v]*(LL)((LL)n-sum[v])*d;
            }

        }

        LL mm = (LL)n*(LL)(n-1)/2;
        printf("%I64d %.2lf\n",ans,x*1.0/mm);

    }

    return 0;
}
View Code

 

posted @ 2017-07-24 16:22  小草的大树梦  阅读(311)  评论(0编辑  收藏  举报