BZOJ1989——bonus奖励计划
题目描述:
输入:
有多组数据,以EOF结束。
对于每一组数据: 第一行包含一个正整数N,表示城市的数目。 接下来的N-1行,每行包含2个整数,Ai、Bi,表示Ai和Bi间有一条双向的旅行通道。
输出:
对于每一组测试数据,输出一行: 为一个实数,表示平均的支付费用,保留(四舍五入)至小数点后6位。
Solution:
这题的大体思路就是去计算某一条人选择的边被国王选择的奖励线路所覆盖的概率
所以对于每一条边,他既被人所选择,又被国王所选择的概率就应该是(
p
a
t
h
t
o
t
2
\frac{path}{tot}^2
totpath2)(
p
a
t
h
path
path 指经过这条边的路径数量,
t
o
t
tot
tot 指所有可能的路径数量)
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=1e4+5;
int n;
struct node{
int to,nxt;
}E[maxn<<1];
int head[maxn],cnt;
void add(int u,int v){
E[++cnt]={v,head[u]};
head[u]=cnt;
}
double ans;
int sz[maxn];
void dfs(int u,int f){
sz[u]=1;
for(int i=head[u];i;i=E[i].nxt){
int v=E[i].to;
if(v==f)continue;
dfs(v,u);
sz[u]+=sz[v];
}
for(int i=head[u];i;i=E[i].nxt){
int v=E[i].to;
if(v==f)continue;
double t=1.0*sz[v]*(n-sz[v])/(n*(n-1)/2);
ans+=t*t;//平方是因为既要被人选,也要被国王选,两个独立的事件
}
}
signed main(){
while(cin>>n){
cnt=0;
memset(head,0,sizeof(head));
memset(E,0,sizeof(E));
for(int i=1;i<n;i++){
int u,v;cin>>u>>v;
add(u,v);add(v,u);
}
ans=0;
memset(sz,0,sizeof(sz));
dfs(1,0);
printf("%.6lf\n",ans);
}
return 0;
}