hdu 5723 最小生成树+dfs (多校)

来源:互联网 发布:unity3d 模拟重力跳跃 编辑:程序博客网 时间:2024/06/03 16:26

题意:
给出一个图,求最小生成树,然后求一下最小生成树的任意两点之间距离的期望。n<=100000,m<=1000000
分析:
期望=任意两点之间的距离和/(n*(n-1)/2)
每条边对距离和的贡献就是这条边的两端的点数之积,可以任选一个点dfs,那么一条边的贡献就是子结点和父结点两端的点数之积,子结点一端的点数是nun,那么父节点一端的点数就是n-num。贡献就是num*(n-num)*w.

#include<bits/stdc++.h>using namespace std;#define mp make_pairtypedef long long ll;typedef pair<int,int>pii;const int INF=1e9;const int N=100000+9;const int M=1000000+9;struct node{    int u,v,w;    bool operator<(const node& rhs)const{        return w<rhs.w;    }};node q[M];vector<pii>e[N];double sum;ll ans;int n,m,fa[M];int findfa(int x){return fa[x]==x?x:fa[x]=findfa(fa[x]);}int dfs(int u,int f){    int num=0;    for(int i=0;i<e[u].size();i++){        int v=e[u][i].first;        if(v==f)continue;        int tmp=dfs(v,u);        num+=tmp;        sum+=1.0*e[u][i].second*tmp*(n-tmp);    }    return num+1;}void init(){    for(int i=1;i<=n;i++)fa[i]=i,e[i].clear();    ans=0;    sum=0;}int main(){    //freopen("f.txt","r",stdin);    int T;scanf("%d",&T);    while(T--){        scanf("%d%d",&n,&m);        init();        for(int i=0;i<m;i++){            scanf("%d%d%d",&q[i].u,&q[i].v,&q[i].w);        }        sort(q,q+m);        for(int i=0;i<m;i++){            int x=findfa(q[i].u),y=findfa(q[i].v);            if(x!=y){                fa[x]=y;                ans+=q[i].w;                e[q[i].u].push_back(mp(q[i].v,q[i].w));                e[q[i].v].push_back(mp(q[i].u,q[i].w));            }        }        dfs(1,0);        printf("%lld %.2lf\n",ans,sum/n/(n-1)*2);    }    return 0;}
0 0
原创粉丝点击