道路修建

来源:互联网 发布:js position 编辑:程序博客网 时间:2024/05/01 13:40

题目简述:

       给你一棵N(N100,000)个节点的树,求出任选两个不同节点的距离的期望值。

 

题目分析:

       这个是在NOI2011Day2 T1的启发下出的一道ws题。

       我们考虑一下这个期望到底是要算什么。

首先一共只有N(N-1)/2种情况,我们只需要把每种情况的答案累加起来就可以了。

注意要用longlong/int64

#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <vector>#define rep(i , n) for(int i = 1 ; i <= n ; ++i)using namespace std;const int M = 1000000 + 10 ;long long sum , sw = 0 ;long long n , node[M] , top = 0;long long son[M] ;bool vis[M] ;struct Edge{    int from , to , w , next ;}edge[M * 2] ;void add_edge(int x , int y , int w){    ++top ;    edge[top].from = x ;    edge[top].to = y ;    edge[top].w = w ;    edge[top].next = node[x] ;    node[x] = top ;}void DFS(int u){    vis[u] = 1 , son[u] = 1 ;    for(int i = node[u] ; i ; i = edge[i].next)    {        int v = edge[i].to , w = edge[i].w ;        if(!vis[v])        {            DFS(v) ;            //sw += (long long)w * son[v] * (n - son[v]) ;            son[u] += son[v] ;        }    }}long long gcd(long long x , long long y){    if(y == 0) return x ;    else return gcd(y , x % y) ;}int main(){    freopen("road.in","r",stdin) ;    freopen("road.out","w",stdout) ;    scanf("%d",&n) ;    sum = (n - 1) * n / 2 ;    rep(i , n - 1)    {        int x , y , z ;        scanf("%d%d%d",&x,&y,&z) ;        add_edge(x , y , z) ;        add_edge(y , x , z) ;    }    //memset(son , 0 , sizeof(son)) ;    DFS(1) ;    rep(i , top)    if(i & 1 == 1)    {        long long Min = min(son[edge[i].from] , son[edge[i].to]) ;        sw += (long long)Min * (n - Min) * edge[i].w ;    }    long long _gcd = gcd(sw , sum) ;    cout << sw / _gcd << "/" << sum / _gcd  << endl ;    return 0;}

0 0
原创粉丝点击