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

来源:互联网 发布:golang http handler 编辑:程序博客网 时间:2024/06/05 03:41

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发现他不会做了,于是他来问你这个问题的答案。

Solution

今天在考场上想的已经有点接近正解,但在处理方式上处理不好,后来才发现正解太强了。

我们设f[i]表示第i个点往上走到自己父亲的期望步数,那么f[x]=yson[x]f[y]+f[x]+1|son[x]|+1+1|son[x]|+1,(yson[x]f[y]+f[x]+1|son[x]|+1表示x先走到x的儿子后再走回x)化简得f[x]=|son[x]|+1+yson[x]f[y]。我们设e(i,j)表示j的父亲i往下走到j的期望步数。那么e(x,y)=zson[x]1+f[z]+e(x,y)|son[x]|+1+1|son[x]|+1+e(fa[x],x)+1+e(x,y)|son[x]|+1。解释一下:zson[x]1+f[z]+e(x,y)|son[x]|+1表示x走到x别的儿子再走回x,最后走到y;e(fa[x],x)+1+e(x,y)|son[x]|+1表示x走到自己的父亲后再走下来到x;1|son[x]|+1表示x一步走到y。化简得e(x,y)=zson[x]f[z]+e(fa[x],x)+|son[x]|+1。然后我们记g[y]=e(x,y)。

最后我们设f[x][0..1]分别表示从下往上走到x和x往下走的最大值,做一下树形dp取最大值即可。

Code

#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<algorithm>#define db doubleusing namespace std;const int maxn=200005;int first[maxn],last[maxn],next[maxn],e[maxn],g[maxn],size[maxn],f[maxn][2];int n,i,t,j,k,l,num,x,y,ans;db ans1;void lian(int x,int y){    last[++num]=y;next[num]=first[x];first[x]=num;}void dg(int x,int y){    int t;    e[x]=size[x];    for (t=first[x];t;t=next[t]){        if (last[t]==y) continue;        dg(last[t],x);        e[x]+=e[last[t]];    }}void dg1(int x,int y){    int t;    for (t=first[x];t;t=next[t]){        if (last[t]==y) continue;        g[last[t]]=e[x]-e[last[t]]+g[x];        dg1(last[t],x);    }}void dg2(int x,int y){    int t,p,q,p1,q1;p=q=p1=q1=0;    for (t=first[x];t;t=next[t]){        if (last[t]==y) continue;        dg2(last[t],x);        f[x][0]=max(f[x][0],f[last[t]][0]+g[last[t]]);        f[x][1]=max(f[x][1],f[last[t]][1]+e[last[t]]);        if (f[last[t]][0]+g[last[t]]>f[p][0]+g[p] || !p) p1=p,p=last[t];        else if (f[last[t]][0]+g[last[t]]>f[p1][0]+g[p1] || !p1) p1=last[t];        if (f[last[t]][1]+e[last[t]]>f[q][1]+e[q] || !q) q1=q,q=last[t];        else if (f[last[t]][1]+e[last[t]]>f[q1][1]+e[q1] || !q1) q1=last[t];    }    if (p!=q) ans=max(ans,f[p][0]+g[p]+f[q][1]+e[q]);    else ans=max(ans,max(f[p][0]+f[q1][1]+g[p]+e[q1],f[p1][0]+g[p1]+f[q][1]+e[q]));}int main(){    freopen("rw.in","r",stdin);freopen("rw.out","w",stdout);    scanf("%d",&n);    for (i=1;i<n;i++)        scanf("%d%d",&x,&y),lian(x,y),lian(y,x),size[x]++,size[y]++;    dg(1,0);    dg1(1,0);    dg2(1,0);    ans1=ans;    printf("%.5lf\n",ans1);}
1 0
原创粉丝点击