【NOIP2016提高A组集训第14场11.12】随机游走

来源:互联网 发布:网络写手排行榜2016 编辑:程序博客网 时间:2024/06/05 06:23

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+(jif[j]+f[i]+1d[i]

就是走到某个儿子再走回来
f[i]=d[i]+(jif[j])d[i]+(d[i]1)f[i]d[i])

把最右边的移项到左边,再化简
f[i]=d[i]+(jif[j])

再设g[i]为从fa[i]到i的期望步数,设k为i的父亲

g[i]=1+g[k]+g[i]+1+(jijif[j]+g[i]+1)d[k]

从父亲走到它的父亲走回来或走到其它儿子再走回来
g[i]=d[i]+(d[i]1)g[i]+g[k]+(jijif[j])d[k]

和上面类似的化简,到最后
g[i]=g[k]+d[k]+(jijif[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 doubleusing 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);}
0 0
原创粉丝点击