随机游走

Description

YJC最近在学习图的有关知识。今天,他遇到了这么一个概念:随机游走。随机游走指每次从相邻的点中随机选一个走过去,重复这样的过程若干次。YJC很聪明,他很快就学会了怎么跑随机游走。为了检验自己是不是欧洲人,他决定选一棵树,每条边边权为 1  1 ,选一对点 s  s  t  t ,从 s  s 开始随机游走,走到t就停下,看看要走多长时间。但是在走了 10000000  10000000 步之后,仍然没有走到 t t。YJC坚信自己是欧洲人,他认为是因为他选的 s  s  t  t 不好,即从 s  s 走到 t  t 的期望距离太长了。于是他提出了这么一个问题:给一棵 n  n 个点的树,问所有点对(i,j)(1i,jn)(i,j)(1≤i,j≤n)中,从 i  i 走到 j  j 的期望距离的最大值是多少。YJC发现他不会做了,于是他来问你这个问题的答案。

Input

第一行包含一个整数 n n,表示点数。
接下来 n1  n−1 行,第 i+1  i+1 行包含两个整数uiuivivi,表示树的一条边。

Output

输出一行,包含一个实数,表示最大的期望距离,保留五位小数。

Sample Input

3
1 2
2 3

Sample Output

4.00000

Data Constraint

对于30%30%的数据,满足n5n≤5
对于50%50%的数据,满足n3000n≤3000
对于100%100%的数据,满足n100000n≤100000

Hint

s=1t=3s=1,t=3,11走到2距离为11,从2走到33的期望距离 d 满足d=0.5(d+2)+0.5d=0.5(d+2)+0.5,解得d=3d=3,所以从11走到3的期望距离为44

Solution

期望题!每次做期望题都没信心。
我们来分析相邻点之间期望值怎么求。
这里写图片描述
不妨设从 x  y  y 的期望步数为e[x,y]e[x,y]
要使当前点到达目标点,会有以下几种可能。
①折返:从WW走到其余点之一,经过一番波折又回到当前点再到目标点

步数f=1+e[x,w]+e[w,p]{11为从 w  x  x 的步数},共有KK种这样的可能

②直达:直接从 W  P  P 

步数f=1f=1,共有 1  1 种这样的可能

然而每一种方案概率都是相等的,即可得

e[w,p]=ki=1(1+e[xi,w]+e[w,p])+1k+1e[w,p]=∑i=1k(1+e[xi,w]+e[w,p])+1k+1

进一步化简可得

e[w,p]=i=1ke[xi,w]+k+1e[w,p]=∑i=1ke[xi,w]+k+1

 d[x]  d[x]  x  x 的度数,又可化得

e[w,p]=i=1ke[xi,w]+d[w]e[w,p]=∑i=1ke[xi,w]+d[w]

所以对于一颗树,x,y∀x,y两点期望都有e[x,y]=e[x,w1]+e[w1,w2]+..+e[w2,y]e[x,y]=e[x,w1]+e[w1,w2]+..+e[w2,y]
即路径期望和。
很像什么,e[x,y]e[x,y]就像是树枝的权值!但要注意是有向的,本题要求最大的点对期望距离,那不就相当于树的直径吗?


 f[i]  f[i] 为结点 i  i 到其父亲的期望值, g[i]  g[i]  i  i 的父亲到结点 i  i 的期望值。
那么根据上述分析就有如下转移:

f[i]=yson[x]f[y]+d[x]f[i]=∑y∈son[x]f[y]+d[x]
g[i]=yson[fa[x]]f[i]+g[fa[x]]+d[fa[x]]g[i]=∑y∈son[fa[x]]−f[i]+g[fa[x]]+d[fa[x]]

 f2[i]  f2[i]  i  i 结点到其子树叶子最大期望, g2[i]  g2[i]  i  i 子树叶子到 i  i 的最大期望。
所以

f2[i]=max(f2[y]+f[y]),yson[x]f2[i]=max(f2[y]+f[y]),y∈son[x]
g2[i]=max(g2[y]+g[y]),yson[x]g2[i]=max(g2[y]+g[y]),y∈son[x]

 p[i]  p[i] 为以 i  i 为根的子树经过 i  i 的最大期望步数。
 i  i 的儿子只有一个,则

p[i]=max(g2[i],f2[i])p[i]=max(g2[i],f2[i])

 i  i 的儿子大于一个,那么

p[i]=max(f[y1]+f2[y1]+g[y2]+g2[y2]),y1,y2son[x]y1y2p[i]=max(f[y1]+f2[y1]+g[y2]+g2[y2]),y1,y2∈son[x]且y1≠y2

于是ans= max(p[i])ans= max(p[i]),一个树形 DP  DP 就搞定了。

Code

const   maxn=100005;
var     tot,x,y,i,n:longint;
        ans:int64;
        g,yy,next:array[0..2*maxn] of longint;
        s,fa,son,f,f2,l1,l2:array[0..maxn] of int64;
function max(x,y:int64):int64;
begin   if x>y then exit(x);exit(y);end;
procedure make(x,y:longint);
begin
    inc(tot);
    yy[tot]:=y;
    next[tot]:=g[x];
    g[x]:=tot;
end;
procedure dfs(x:longint);
var i,y:longint;
begin
    i:=g[x];
    while i<>0 do begin
        y:=yy[i];
        if fa[x]<>y then begin
            fa[y]:=x;
            son[y]:=1;
            dfs(y);
            son[x]:=son[x]+1;
            s[x]:=f[y]+s[x];
        end;
        i:=next[i];
    end;
    f[x]:=s[x]+son[x];
end;
procedure dfs2(x:longint);
var     a1,a2,b1,b2,i,y:longint;
begin
    i:=g[x];
    if x<>1 then
        f2[x]:=s[fa[x]]-f[x]+f2[fa[x]]+son[fa[x]];
        a1:=0;a2:=0;
        b1:=0;b2:=0;
    while i<>0 do begin
        y:=yy[i];
        if fa[x]<>y then begin
            dfs2(y);
            if l1[y]+f[y]>f[a1]+l1[a1] then begin
                a2:=a1;
                a1:=y;
            end else if f[y]+l1[y]>f[a2]+l1[a2] then a2:=y;
            if f2[y]+l2[y]>f2[b1]+l2[b1] then begin
                b2:=b1;
                b1:=y;
            end else if f2[y]+l2[y]>f2[b2]+l2[b2] then b2:=y;
        end;
        i:=next[i];
    end;
    l1[x]:=l1[a1]+f[a1];
    l2[x]:=l2[b1]+f2[b1];
    if (son[x]=1) or ((son[x]=2) and (x<>1)) then ans:=max(max(ans,l1[x]),l2[x]) else
    if a1<>b1 then ans:=max(ans,l1[x]+l2[x]) else begin
        ans:=max(ans,f[a1]+l1[a1]+f2[b2]+l2[b2]);
        ans:=max(ans,f[a2]+l1[a2]+f2[b1]+l2[b1]);
    end;


end;
begin
assign(input,'rw.in');reset(input);
assign(output,'rw.out');rewrite(output);
    readln(n);
    for i:=1 to n-1 do begin
        readln(x,y);
        make(x,y);
        make(y,x);
    end;
    dfs(1);
    dfs2(1);
    writeln(ans,'.00000');
close(input);
close(output); 
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值