Description
YJC最近在学习图的有关知识。今天,他遇到了这么一个概念:随机游走。随机游走指每次从相邻的点中随机选一个走过去,重复这样的过程若干次。YJC很聪明,他很快就学会了怎么跑随机游走。为了检验自己是不是欧洲人,他决定选一棵树,每条边边权为1,选一对点s和t,从s开始随机游走,走到t就停下,看看要走多长时间。但是在走了10000000步之后,仍然没有走到t。YJC坚信自己是欧洲人,他认为是因为他选的s和t不好,即从s走到t的期望距离太长了。于是他提出了这么一个问题:给一棵n个点的树,问所有点对(i,j)(1≤i,j≤n)中,从i走到j的期望距离的最大值是多少。YJC发现他不会做了,于是他来问你这个问题的答案。
Input
第一行包含一个整数n,表示点数。
接下来n-1行,第(i+1)行包含两个整数ui和vi,表示树的一条边。
Output
输出一行,包含一个实数,表示最大的期望距离,保留五位小数。
Sample Input
3
1 2
2 3
Sample Output
4.00000
Data Constraint
对于30%的数据,满足n≤5。
对于50%的数据,满足n≤3000。
对于100%的数据,满足n≤100000。
Solution
突然想到了一道叫做游走的题,然而我没做过
发现这个东西比较奇怪,所以比赛时直接弃了
设f[i]表示从i到fa[i]的期望步数,fa[i]为i的父亲,d[i]为i的度数
f[i]=1+(∑j是i的儿子f[j]+f[i]+1)d[i]
就是走到某个儿子再走回来
f[i]=d[i]+(∑j是i的儿子f[j])d[i]+(d[i]−1)f[i]d[i])
把最右边的移项到左边,再化简
f[i]=d[i]+(∑j是i的儿子f[j])
再设g[i]为从fa[i]到i的期望步数,设k为i的父亲
g[i]=1+g[k]+g[i]+1+(∑j是i的儿子且j不是if[j]+g[i]+1)d[k]
从父亲走到它的父亲走回来或走到其它儿子再走回来
g[i]=d[i]+(d[i]−1)g[i]+g[k]+(∑j是i的儿子且j不是if[j])d[k]
和上面类似的化简,到最后
g[i]=g[k]+d[k]+(∑j是i的儿子且j不是if[j])
这样就可以求出两点之间的距离了
每次枚举lca取MAX作为答案
Code
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 101000
#define db double
using namespace std;
int next[N*10],to[N*10],last[N],tot=0,n,m,d[N],fa[N],f[N],g[N],mx[N],ma[N],ans;
void putin(int x,int y)
{
next[++tot]=last[x];last[x]=tot;to[tot]=y;
}
void dg(int x,int z)
{
int bz=1;
for(int i=last[x];i;i=next[i])
if(to[i]!=z) fa[to[i]]=x,dg(to[i],x),f[x]+=f[to[i]],bz=0;
f[x]+=d[x];
}
void dg2(int x,int z)
{
int jy=0;
for(int i=last[x];i;i=next[i]) if(to[i]!=z) jy+=f[to[i]];
for(int i=last[x];i;i=next[i])
if(to[i]!=z) g[to[i]]=g[x]+d[x]+jy-f[to[i]],dg2(to[i],x);
}
void dfs(int x,int z)
{
int cmx=0,cma=0,mx1,mx2,ma1,ma2;
for(int i=last[x];i;i=next[i])
if(to[i]!=z)
{
int y=to[i];
dfs(y,x);
int jy=mx[y]+f[y];
if(jy>mx[x]) cmx=mx[x],mx2=mx1,mx[x]=jy,mx1=y;
else if(jy>cmx) cmx=jy,mx2=y;
jy=ma[y]+g[y];
if(jy>ma[x]) cma=ma[x],ma2=ma1,ma[x]=jy,ma1=y;
else if(jy>cma) cma=jy,ma2=y;
}
if(mx1==ma1) ans=max(ans,max(mx[x]+cma,ma[x]+cmx));
else ans=max(ans,mx[x]+ma[x]);
}
int main()
{
freopen("rw.in","r",stdin);freopen("rw.out","w",stdout);
scanf("%d",&n);
fo(i,1,n-1)
{
int x,y;scanf("%d%d",&x,&y);
putin(x,y);putin(y,x);d[y]++;d[x]++;
}
dg(1,0);
dg2(1,0);
dfs(1,0);
printf("%d.00000",ans);
return 0;
fclose(stdin);fclose(stdout);
}