Average distance&&dfs&&vector

题目链接:点击打开链接

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 (d 01 + d 02 + d 03 + d 04 + d 12 +d 13 +d 14 +d 23 +d 24 +d 34)/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
分析:要求d 01 + d 02 + d 03 + d 04 +…don+ d 12 +d 13 +d 14+…don +d 23 +d 24 +d 34+…don+……可把这些边看成要走的路,对于其中的任意一条路要走的次数都是子树的节点数(包括自己)*父树的节点数,对其再乘以相应的权值,求和,就是要求的答案。对于结点数的求取,可利用如下方法:把0看成父亲,其余全为他的孩子,利用dfs依次对各个节点遍历。

代码:

#include <iostream>
#include<cstdio>
#include<vector>
#include<cstring>
const int maxn=1e4+5;
using namespace std;
vector<pair<int ,int> >m[maxn];
int t,n,k;
int a[maxn];//i子树(包括自己)节点的个数
int vis[maxn];//标记是否访问过次节点
double sum=0;
int dfs(int x,int y)
{
    vis[x]=1;
    if(m[x].size()==1&&x!=0)
    {
        sum+=1.0*(n-1)*y;
        return a[x];
    }
    for(int i=0;i<m[x].size();i++)
    {
        int v=m[x][i].first;
        int w=m[x][i].second;
        if(!vis[v])
        {
            a[x]+=dfs(v,w);
        }
    }
    sum+=a[x]*1.0*(n-a[x])*y;
}
int main()
{
    cin>>t;
    while(t--)
    {
        sum=0;
        memset(vis,0,sizeof(vis));
        cin>>n;
        for(int i=0;i<=n;i++)
        {
            a[i]=1;
            m[i].clear();
        }
        for(int i=0;i<n-1;i++)
        {
            int x,y,v;
            cin>>x>>y>>v;
            m[x].push_back(make_pair(y,v));
            m[y].push_back(make_pair(x,v));
        }
        dfs(0,0); a[0]=0;
        double num=1.0*n*(n-1)/2;
        printf("%.7lf\n",sum/num);//一注意要精确度
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值