题目大意
:
题目大意:
题目大意:
给定一棵
n
个节点的树,点之间有长度为
1
的路径,求起始点为任意点时走的路径长度的期望最大值
给定一棵n个节点的树,点之间有长度为1的路径,求起始点为任意点时走的路径长度的期望最大值
给定一棵n个节点的树,点之间有长度为1的路径,求起始点为任意点时走的路径长度的期望最大值
(不会走重复的边,且走每一条边的概率一致
)
(不会走重复的边,且走每一条边的概率一致)
(不会走重复的边,且走每一条边的概率一致)
题目分析
:
题目分析:
题目分析:
可以考虑换根
D
P
,
设
d
p
x
表示从
x
开始向下走经过节点数的期望
可以考虑换根DP,设dp_x表示从x开始向下走经过节点数的期望
可以考虑换根DP,设dpx表示从x开始向下走经过节点数的期望
易知
d
p
x
=
1
+
1
∣
s
o
n
x
∣
∑
s
∈
s
o
n
x
d
p
s
易知dp_x=1+\frac{1}{ \left\vert son_x\right\vert }\sum_{s\in son_x}dp_s
易知dpx=1+∣sonx∣1∑s∈sonxdps
接下来,可以设
g
x
表示以
x
为起始点的期望
接下来,可以设g_x表示以x为起始点的期望
接下来,可以设gx表示以x为起始点的期望
由于我们计算
d
p
数组时必以一点为根节点,不妨为
1
,
记算完
d
p
数组后,那么
g
1
=
d
p
1
由于我们计算dp数组时必以一点为根节点,不妨为1,记算完dp数组后,那么g_1=dp_1
由于我们计算dp数组时必以一点为根节点,不妨为1,记算完dp数组后,那么g1=dp1
接下来便考虑换根
D
P
,
对于
v
,我们假设已知
v
的父亲的值
g
u
,首先考虑
v
的子树内的贡献,可知贡献为
∑
s
∈
s
o
n
v
d
p
s
,
由
d
p
式子的变形可知
∑
s
∈
s
o
n
v
d
p
s
=
(
d
p
v
−
1
)
∗
∣
s
o
n
v
∣
,
显然可以
O
(
1
)
求出
接下来便考虑换根DP,对于v,我们假设已知v的父亲的值g_u,首先考虑v的子树内的贡献,可知贡献为\sum_{s\in son_v}dp_s,由dp式子的变形可知\sum_{s\in son_v}dp_s=(dp_v-1)*\left\vert son_v\right\vert,显然可以O(1)求出
接下来便考虑换根DP,对于v,我们假设已知v的父亲的值gu,首先考虑v的子树内的贡献,可知贡献为∑s∈sonvdps,由dp式子的变形可知∑s∈sonvdps=(dpv−1)∗∣sonv∣,显然可以O(1)求出
再考虑
v
的父节点的贡献,可知贡献为
∣
s
o
n
u
+
1
∣
∗
g
u
−
d
p
v
−
1
∣
s
o
n
u
∣
再考虑v的父节点的贡献,可知贡献为\frac{\left\vert son_u+1\right\vert*g_u-dp_v-1}{\left\vert son_u\right\vert}
再考虑v的父节点的贡献,可知贡献为∣sonu∣∣sonu+1∣∗gu−dpv−1
最后还有
v
对自己的贡献
1
最后还有v对自己的贡献1
最后还有v对自己的贡献1
故可以得出转移式
g
v
=
1
∣
s
o
n
v
+
1
∣
∗
(
(
d
p
v
−
1
)
∗
∣
s
o
n
v
∣
+
∣
s
o
n
u
+
1
∣
∗
g
u
−
d
p
v
−
1
∣
s
o
n
u
∣
)
+
1
故可以得出转移式g_v=\frac{1}{\left\vert son_v+1\right\vert}*((dp_v-1)*\left\vert son_v\right\vert+\frac{\left\vert son_u+1\right\vert*g_u-dp_v-1}{\left\vert son_u\right\vert})+1
故可以得出转移式gv=∣sonv+1∣1∗((dpv−1)∗∣sonv∣+∣sonu∣∣sonu+1∣∗gu−dpv−1)+1
最后答案便为
m
a
x
i
=
1
n
g
i
−
1
最后答案便为max_{i=1}^ng_i-1
最后答案便为maxi=1ngi−1
时间复杂度为
O
(
n
)
时间复杂度为O(n)
时间复杂度为O(n)
参考代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int M=100007;
int n;
vector<int> G[M];
double dp[M],g[M];
void DFS1(int now,int fa){
int v;
double sum=0;
for(int i=0;i<G[now].size();i++){
v=G[now][i];
if(fa==v) continue;
DFS1(v,now);
sum+=dp[v];
}
if(now==1)dp[now]=1+sum/G[now].size();
else if(G[now].size()==1) dp[now]++;
else dp[now]=1+sum/(G[now].size()-1);
}
void DFS2(int now,int fa){
int v;
double sum;
for(int i=0;i<G[now].size();i++){
v=G[now][i];
if(fa==v) continue;
sum=0;
sum=sum+(dp[v]-1)*(G[v].size()-1);
if(G[now].size()>1) {
sum=sum+(g[now]*G[now].size()-dp[v]-1)/(G[now].size()-1);
}else {
sum=sum+1;
}
g[v]=sum/(G[v].size())+1;
DFS2(v,now);
}
}
int main(){
ios::sync_with_stdio(false);
int a,b;
cin>>n;
for(int i=1;i<n;i++){
cin>>a>>b;
G[a].push_back(b);
G[b].push_back(a);
}
DFS1(1,-1);g[1]=dp[1];
// for(int i=1;i<=4;i++){
// cout<<dp[i]<<" ";
// }
// cout<<"\n";
DFS2(1,-1);
// for(int i=1;i<=4;i++){
// cout<<g[i]<<" ";
// }
double anq=0;
for(int i=1;i<=n;i++) anq=max(anq,g[i]);
cout<<fixed<<setprecision(3)<<anq-1<<"\n";
}