2.道路修建
描述 Description
liouzhou_101最悲痛的回忆就是NOI2011的道路修建,当时开了系统堆栈,结果无限RE…
出于某种报复心理,就把那题神奇了一下:
在 Z星球上有N个国家,这N个国家之间只能建造N-1条道路且全部建完这N-1条道路后这N个国家相互连通,修建每条道路都有相应的花费。但是他们都很吝啬,于是决定只随机选出两个不同的国家(为了国家的平等,当然这两个国家是无顺序可言的),建造该建造的道路,使得这两个国家相互连通,自然费用越少越 好。然后问你,在所有情况中,修建道路花费的平均值。
假若您认为本题题目叙述太渣,那就形象地描述一遍:给出一棵边上带权的树,求任意两个不同的点的距离的期望值。
输入格式 InputFormat
第一行包括一个正整数N,N表示国家的数量。
接下来N-1行每行包括三个正整数x、y和w,表示国家x和国家y之间有一条花费为w的道路。
输出格式 OutputFormat
仅一行,包含一个最简分数,格式为A/B,详见样例。
样例输入 SampleInput [复制数据]
4
1 2 1
1 3 1
1 4 1
样例输出 SampleOutput [复制数据]
3/2
数据范围和注释 Hint
对于这组测资,共存在6种情况:
①(1,2) 距离 1; ②(1,3) 距离 1;
③(1,4) 距离 1; ④(2,3) 距离 2;
⑤(2,4) 距离 2; ⑥(3,4) 距离 2;
所以平均值为(1+1+1+2+2+2)/6=3/2。
30%的数据,满足n<=1,000;
50%的数据,满足n<=10,000;
100%的数据,满足1<=n<=100,000,1<=w<=1,000。
时间限制 TimeLimitation
1s
解:随便找个点dfs,假设节点y下有s[y]个点(包括y),他的父节点为t,通过这条路就有s[y]*(n-s[y])次,统计一下即可。
注意:全开long long
来源:“扫地”杯III NOIP2012模拟赛 day1 第二题
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #define sc(x) scanf("%d",&x) 7 #define scl(x) scanf("%lld",&x) 8 #define man 101000 9 #define ll long long 10 using namespace std; 11 ll n; 12 struct edge 13 { 14 ll next,to,dis; 15 }e[man*2]; 16 ll s[man]; 17 bool vis[man]; 18 ll sum=0; 19 ll head[man*2],num=0; 20 void add(int from,int to,int dis) 21 { 22 e[++num].next=head[from]; 23 e[num].to=to; 24 e[num].dis=dis; 25 head[from]=num; 26 } 27 ll gcd(ll a,ll b) 28 { 29 if(b==0) 30 return a; 31 else return gcd(b,a%b); 32 } 33 void dfs(ll t) 34 { 35 s[t]=1;vis[t]=1; 36 for(int i=head[t];i;i=e[i].next) 37 { 38 ll to=e[i].to; 39 if(!vis[to]) 40 { 41 dfs(to); 42 sum+=e[i].dis*(n-s[to])*s[to]; 43 s[t]+=s[to]; 44 } 45 } 46 } 47 int main() 48 { freopen("road.in","r",stdin); 49 freopen("road.out","w",stdout); 50 scl(n); 51 for(int i=1;i<n;i++) 52 { 53 int x,y,z; 54 sc(x);sc(y);sc(z); 55 add(x,y,z); 56 add(y,x,z); 57 } 58 dfs(1); 59 n=n*(n-1)/2; 60 if(n==0) 61 n=1; 62 ll ans=gcd(sum,n); 63 printf("%lld/%lld",sum/ans,n/ans); 64 return 0; 65 }