题目大意
给出一棵树,边权为一,一个点走到相邻点的概率相等,求一对点对期望最多走多少步能到达。
解题思路
可以推出走过一条边的期望,考虑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;
}