hdu5723(树形dp+最小生成树)

来源:互联网 发布:淘宝客怎么赚钱 编辑:程序博客网 时间:2024/05/05 20:11

链接:点击打开链接

题意:在最小生成树的基础上求出任意两点间距离的期望

代码:

#include <vector>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <iostream>#include <algorithm>using namespace std;const long long SIZE=100005;long long n,dp[SIZE],num[SIZE],used[SIZE];struct node{    long long to,cost;};vector<node> G[SIZE];void dfs1(long long s,long long sum){    long long i,tmp;    dp[1]+=sum;                                 //求出根节点的到其他节点的和    used[s]=1;                                  //和每个节点的子节点数    for(i=0;i<G[s].size();i++){        tmp=G[s][i].to;        if(!used[tmp]){        dfs1(tmp,sum+G[s][i].cost);        num[s]+=num[tmp];        }    }}void dfs2(long long s){    long long i,tmp;    used[s]=1;    for(i=0;i<G[s].size();i++){        tmp=G[s][i].to;        if(!used[tmp]){        dp[tmp]+=(dp[s]+(n-num[tmp])*G[s][i].cost-num[tmp]*G[s][i].cost);        dfs2(tmp);        }                                       //根据每个节点儿子节点的个数求出每个节点    }                                           //到其他所有节点的和}long long V,E;long long par[100005],ran[100005],vis[100005];void init(long long n){    long long i;    for(i=0;i<=n;i++){        ran[i]=0;        par[i]=i;    }}long long find(long long x){    if(par[x]==x)    return x;    return par[x]=find(par[x]);}void unite(long long x,long long y){    x=find(x);    y=find(y);    if(x==y)    return;    if(ran[x]<ran[y])    par[x]=y;    else{        par[y]=x;        if(ran[x]==ran[y])        ran[x]++;    }}bool same(long long x,long long y){    return find(x)==find(y);}struct node1{    long long u,v,cost;};bool cmp(node1 a,node1 b){    return a.cost<b.cost;}node1 es[1000005];long long kruskal(){    long long i;    long long res=0;    init(V);    sort(es,es+E,cmp);    for(i=0;i<E;i++){        node1 e=es[i];        if(!same(e.u,e.v)){            unite(e.u,e.v);            G[e.u].push_back((node){e.v,e.cost});            G[e.v].push_back((node){e.u,e.cost});            res+=e.cost;        }    }    return res;}                                               //最小生成树int main(){                                     //跟51nod1405几乎一样    long long a,b,w,m,i,t,ans,sum;              //http://blog.csdn.net/stay_accept/article/details/50835286    scanf("%I64d",&t);    while(t--){        scanf("%I64d%I64d",&n,&m);        V=n,E=m;        for(i=1;i<=n;i++)        G[i].clear();        memset(vis,0,sizeof(vis));        for(i=0;i<E;i++)        scanf("%I64d%I64d%I64d",&es[i].u,&es[i].v,&es[i].cost);        ans=kruskal();        fill(num,num+n+1,1);        memset(dp,0,sizeof(dp));        memset(used,0,sizeof(used));        dfs1(1,0);        memset(used,0,sizeof(used));        dfs2(1);        sum=0;        for(i=1;i<=n;i++)        sum+=dp[i];        printf("%I64d %.2lf\n",ans,sum*1.0/(n*(n-1)));    }    return 0;}

0 0
原创粉丝点击