hdu 2376 Average distance 樹形dp求樹上所有兩兩點間的和

Average distance

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1266    Accepted Submission(s): 456
Special Judge

 

Problem Description

Given a tree, calculate the average distance between two vertices in the tree. For example, the average distance between two vertices in the following tree is (d01 + d02 + d03 + d04 + d12 +d13 +d14 +d23 +d24 +d34)/10 = (6+3+7+9+9+13+15+10+12+2)/10 = 8.6.
 

 

 

 

Input

On the first line an integer t (1 <= t <= 100): the number of test cases. Then for each test case:

One line with an integer n (2 <= n <= 10 000): the number of nodes in the tree. The nodes are numbered from 0 to n - 1.

n - 1 lines, each with three integers a (0 <= a < n), b (0 <= b < n) and d (1 <= d <= 1 000). There is an edge between the nodes with numbers a and b of length d. The resulting graph will be a tree.
 

 

 

Output

For each testcase:

One line with the average distance between two vertices. This value should have either an absolute or a relative error of at most 10-6
 

 

 

Sample Input


 

1 5 0 1 6 0 2 3 0 3 7 3 4 2

 

 

Sample Output


 

8.6

 


題意:

    給你一棵樹和邊的權值,要你求樹上兩兩距離的平均和。

 

做法:

    樹形dp求。因爲如果枚舉任意兩個點肯定會T,所以不如求每個邊的貢獻次數乘上距離,最後除總路徑。每個邊的貢獻次數等於該邊兩端頂點個數的積,所以這題就是求每個頂點子樹的節點個數。只用做一次dfs就好,dfs寫法見代碼。最後注意要用long long 。


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn=100005;
struct node{
    int to,next;
    ll w;
}e[maxn<<1];
int n,head[maxn],cnt,sz[maxn];
ll fac[maxn];
ll dp[maxn];
void add(int u,int v,ll w){
    e[cnt].to=v,e[cnt].next=head[u];
    e[cnt].w=w,head[u]=cnt++;
}
void dfs(int x,int fa){
    sz[x]=1;
    for(int i=head[x];~i;i=e[i].next){
        int t=e[i].to,w=e[i].w;
        if(fa==t) continue;
        dfs(t,x);
        sz[x]+=sz[t];
        dp[x]=(dp[x]+dp[t]+(double)(n-sz[t])*sz[t]*w);
    }
}
int main(){
    int x,y,t;
    ll w;
    cin>>t;
    while(t--){
        memset(head,-1,sizeof(head));
        memset(dp,0,sizeof(dp));
        cnt=0;
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            scanf("%d%d%lld",&x,&y,&w);
            x++,y++;
            add(x,y,w);
            add(y,x,w);
        }
        dfs(1,-1);
        double s=n*(n-1);
        printf("%.11f\n",((double)dp[1])*2.0/s);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章