HDU 5723 Abandoned country

http://acm.hdu.edu.cn/showproblem.php?pid=5723
大意是先用最小生成树把路联通,在求出所有点的距离,
最小生成树+求任意两点距离的期望。
最小生成树就不讲了。求期望可以先求出每个边的贡献度,这条边的上下所有点数相乘就是这条边要经过几次,再乘上边长就是这个边的贡献度。

#include<algorithm>
#include <iostream>
#include  <cstring>
#include   <cstdio>
#include   <vector>
#include    <queue>
#include      <map>
#include      <set>
using namespace std;
#define N 100010
struct Node
{
    int u,v,w;
    Node() {}
    Node(int _u,int _v,int _w):u(_u),v(_v),w(_w) {}
};
struct Edge
{
    int v,w;
    Egde(){}
    Edge(int _v,int _w):v(_v),w(_w) {}
};
vector<Node>node;
vector<Edge>edge[N];
int n,m,pre[N];
double dp[N];
int sum[N];
bool cmp(const Node &x,const Node &y)
{
    return x.w<y.w;
}
int Find(int a)
{
    if(a==pre[a])
    {
        return a;
    }
    return pre[a]=Find(pre[a]);
}
long long Kruskal()
{
    sort(node.begin(),node.end(),cmp);
    for(int i=1; i<=n; i++)
    {
        pre[i]=i;
    }
    long long ans=0;
    for(int i=0,u,v; i<(int)node.size(); i++)
    {
        u=node[i].u,v=node[i].v;
        u=Find(u),v=Find(v);
        if(u==v)
        {
            continue;
        }
        pre[u]=v;
        ans+=(long long)node[i].w;
        edge[node[i].v].push_back(Edge(node[i].u,node[i].w));
        edge[node[i].u].push_back(Edge(node[i].v,node[i].w));
    }
    return ans;
}
void dfs(int root,int father)
{
    sum[root]=1;
    for(int i=0; i<(int)edge[root].size(); i++)
    {
        int son=edge[root][i].v;
        if(son==father)
        {
            continue;
        }
        dfs(son,root);
        sum[root]+=sum[son];
        dp[root]+=dp[son]+((double)(n-sum[son])*sum[son])*edge[root][i].w;
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        node.clear();
        for(int i=0,a,b,c; i<m; i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            node.push_back(Node(a,b,c));
        }
        for(int i=0; i<=n; i++)
        {
            edge[i].clear();
        }
        long long ans=Kruskal();
        memset(dp,0,sizeof(dp));
        memset(sum,0,sizeof(sum));
        dfs(1,0);
        double ANS=dp[1];
        ANS=ANS/n;
        ANS=ANS/(n-1)*2;
        printf("%lld ",ans);
        printf("%.2lf\n",ANS);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lxworld123/article/details/52516743