题目大意
给出一棵树,边权为一,一个点走到相邻点的概率相等,求一对点对期望最多走多少步能到达。
解题思路
可以推出走过一条边的期望,考虑lca为i的路径贡献,找到走到i和从i出发不同子树和最远的路径,和答案取max即可。
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define min(a,b) ((a<b)?a:b)
#define max(a,b) ((a>b)?a:b)
#define fo(i,j,k) for (int i=j;i<=k;i++)
#define fd(i,j,k) for (int i=j;i>=k;i--)
using namespace std;
int const maxn=1e5 +1 ,maxm=20 +1 ,mod=998244353 ,size=1048576 ;
int n,gra,ans,begin [maxn+10 ],f[maxn+10 ],g[maxn+10 ],
du[maxn+10 ],to [maxn*2 +10 ],next[maxn*2 +10 ];
void insert(int u,int v){
to [++gra]=v;
next[gra]=begin [u];
begin [u]=gra;
}
void dfs(int now,int pre){
f[now]=du[now];
for (int i=begin [now];i;i=next[i])
if (to [i]!=pre){
dfs(to [i],now);
f[now]+=f[to [i]];
}
}
void dfss(int now,int pre){
int tmp=0 ;
for (int i=begin [now];i;i=next[i])
if (to [i]!=pre)tmp+=f[to [i]];
for (int i=begin [now];i;i=next[i])
if (to [i]!=pre){
g[to [i]]=g[now]+du[now]+tmp-f[to [i]];
dfss(to [i],now);
}
}
void dfsss(int now,int pre){
for (int i=begin [now];i;i=next[i])
if (to [i]!=pre){
dfsss(to [i],now);
ans=max(ans,max(f[to [i]],g[to [i]]));
}
int f1=0 ,f2,f3=0 ,f4,g1=0 ,g2,g3=0 ,g4;
for (int i=begin [now];i;i=next[i])
if (to [i]!=pre){
if (f[to [i]]>f1){
f3=f1;f4=f2;
f1=f[to [i]];
f2=to [i];
}else if (f[to [i]]>f3){
f3=f[to [i]];
f4=to [i];
}
if (g[to [i]]>g1){
g3=g1;g4=g2;
g1=g[to [i]];
g2=to [i];
}else if (g[to [i]]>g3){
g3=g[to [i]];
g4=to [i];
}
}
if (f[now]==1 )return ;
if (f2!=g2)ans=max(ans,f1+g1);
if (f4!=g2)ans=max(ans,f3+g1);
if (f2!=g4)ans=max(ans,f1+g3);
f[now]+=f1;g[now]+=g1;
}
int main(){
freopen("d.in" ,"r" ,stdin);
freopen("d.out" ,"w" ,stdout);
scanf("%d" ,&n);
fo(i,1 ,n-1 ){
int u,v;scanf("%d%d" ,&u,&v);
du[u]++;du[v]++;insert(u,v);insert(v,u);
}
dfs(1 ,0 );
dfss(1 ,0 );
dfsss(1 ,0 );
printf("%.5lf" ,(double)ans);
return 0 ;
}