zoukankan      html  css  js  c++  java
  • 2016 Multi-University Training Contest 1 Abandoned country

    这题先求出最小生成树,然后在最小生成树中求任意两个点之和的平均数。。因为最小生成树是唯一的,所以期望也就只有一个。求最小生成树的时候把树存起来。求任意两点之和的时候我们求出一条边在求和的时候用了多少次,也就是求该边的左右端点有多少个比如一条边左右两边有A,B个端点,那么利用的次数也就是A*B。
    我们可以用dfs来实现,用sum数组表示k点子树上的点(包括他自己),那么kf父亲那边的点就是n-sum[k]。最后载除一个n*(n-1)/2就可得到答案。

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    #include<map>
    #include<set>
    #include<vector>
    using namespace std;
    const int N=100005;
    const int maxn=1001000;
    struct node
    {
        int v;
        __int64 len; 
    };
    vector<node>G[2*N];
    struct Node
    {
        int u,v;
        __int64 w;  
    };
    int tol;
    Node edge[2*maxn];
    void addedge(int u,int v,__int64 w)
    {
        edge[tol].u=u;
        edge[tol].v=v;
        edge[tol++].w=w;
    }
    double dp;
    __int64 sum[N];
    int f[N];
    __int64 n;
    int m;
    bool cmp(Node a,Node b)
    {
        return a.w<b.w;
    } 
    int find(int x)
    {
        return f[x]==x?x:f[x]=find(f[x]);
    }
    __int64 kulasal()
    {
        __int64 ans=0;
        for(int i=1;i<=n;i++)
        f[i]=i;
        int cnt=0;
        sort(edge,edge+tol,cmp);
        for(int i=0;i<tol;i++)
        {
            int u=edge[i].u;
            int v=edge[i].v;
            int w=edge[i].w;
            int fx=find(u);
            int fy=find(v); 
            if(fx!=fy)
            {
                f[fx]=fy;
                ans+=w;
                node p1,p2;
                p1.v=u;
                p1.len=w;
                p2.v=v;
                p2.len=w;
                G[u].push_back(p2);
                G[v].push_back(p1); 
                cnt++;
            }
            if(cnt==n-1)
            break;
        }
        return ans;
    }
    void dfs(int root,int father)
    {
        sum[root]=1;
        for(int i=0;i<G[root].size();i++)
        {
            int son=G[root][i].v;
            int len=G[root][i].len;
            if(son==father)
            continue;
            dfs(son,root);
            sum[root]+=sum[son];
            dp+=(sum[son]*(n-sum[son]))*(double)len;
        }
    }
    int main()
    {
             int T;
             scanf("%d",&T);
             while(T--)
             {
             tol=0;
             for(int i=1;i<=n;i++)
             G[i].clear();
            scanf("%I64d %d",&n,&m);
            for(int i=0;i<m;i++)
            {
                int u,v,w;
                scanf("%d %d %64d",&u,&v,&w);
                addedge(u,v,w);
                addedge(v,u,w);
            } 
             __int64 S=kulasal();
             memset(sum,0,sizeof(sum));
             dp=0;
             dfs(1,-1);
             __int64 s=n*(n-1)/2;
             double ans=dp/(double)s;
             printf("%I64d %0.2f
    ",S,ans); 
        }
        return 0;
    } 
    
    
  • 相关阅读:
    DS博客作业02--栈和队列
    DS博客作业02--线性表
    c博客06-结构
    c博客作业05--指针
    C博客作业04--数组
    博客作业03-函数
    循环结构
    c博客作业01--分支、顺序结构
    我的第一篇博客
    Macos安装JDK1.8
  • 原文地址:https://www.cnblogs.com/NaCl/p/9580113.html
Copyright © 2011-2022 走看看