1. 程式人生 > >hdu2376 Average distance (樹形dp)

hdu2376 Average distance (樹形dp)

  這題主要是求任意兩點之間的距離之和。首先通過列舉起點終點來求的話是O(N^2),會超時的,這題要換種思路,通過算每條邊的貢獻來得到任意兩點之間的距離之和,每條邊的貢獻就是其2端的點數的乘積再乘以對應的邊權,求每條邊2端的點數就用dfs即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+10;
#define ll long long
struct node
{
    int v;
    ll w;
    node(int vv,ll ww)
    {
        v=vv;
        w=ww;
    }
};
vector<node>g[maxn];
ll ans,num[maxn];//num[i]表示子樹i對應的節點的個數
int n;
void dfs(int now,int fa)
{
    num[now]=1;
    for(int i=0;i<g[now].size();i++)
    {
        int v=g[now][i].v;
        ll w=g[now][i].w;
        if(v==fa) continue;
        dfs(v,now);
        num[now]+=num[v];
        ans+=w*(n-num[v])*num[v];
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ans=0;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            g[i].clear(),num[i]=0;
        for(int i=1;i<=n-1;i++)
        {
            int u,v;
            ll w;
            scanf("%d %d %lld",&u,&v,&w);
            g[u].push_back(node(v,w));
            g[v].push_back(node(u,w));
        }
        dfs(0,-1);
        int tmp=n*(n-1)/2;
        printf("%.6lf\n",ans*1.0/tmp);
    }
    return 0;

}