好久没有写过题解了……现在感觉以前的题解弱爆了,还有这么多访问量……

没有考虑别人的感受,没有放描述、代码,题解也写得歪歪扭扭。

并且我要强烈谴责某些写题解的代码不打注释的人,像天书那样,不是写给普通人看的。

原题点这(JZOJ)


描述

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。

Hint

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


分析

首先普及一下期望是什么东西。

如果第i个状况的概率为p[i],所花的代价为w[i],那么期望e是

e=∑p[i]∗w[i]

期望具有一些奇怪的性质。

在这一题中,如果从X到Y的期望距离为a,从Y到Z的期望距离为b,那么从X到Z的期望距离为a+b

但其实我也不知道是为什么。

首先我们知道,这是一棵树。这意味着两个点之间有且只有一条路径。

所以可以设f[x]表示从x到x的父亲的期望距离,g[x]表示从x的父亲到x的期望距离。

求出f和g后就可以随意地求出两点之间的期望距离了。

考虑树形DP。设d[x]表示x的度(即与其相连的边)

先求f[x]

分两种情况:

1. x直接跳上x的父亲

2. x跳到x的儿子,经过乱跳后跳回x,再乱跳跳到x的父亲

f[x]=1d[x]∗1+(∑son1d[x]∗(1+f[son]+f[x]))

第二种情况中,跳到son距离为1,从son跳回来距离为f[son],再跳上去距离为f[x]

因为左右都有f[x],我们应将f[x]移到左边。

可以手推一下,就变成下面这个式子

f[x]=d[x]+∑sonf[son]

再求g

分三种情况:

1. x的父亲直接跳到x

2. x的父亲跳到x的爷爷,再乱跳到x的父亲,再乱跳到x

3. x的父亲跳到x的兄弟,再乱跳回x的父亲,再乱跳到x

g[x]=1d[father]∗1+1d[father]∗(1+g[father]+g[x])+(∑brother1d[father]∗(1+f[brother]+g[x]))

原因差不多了,仔细想一下就行了。

可以化简为

g[x]=d[father]+g[father]+∑brotherf[brother]

求f和g,分别用两个递归就能很方便地O(n)求出了。

接下来就很好搞了,类似于求一棵树的直径。若从X到Y,那么路径就是X->LCA(X,Y)->Y

设x.fu表示从x的某个后代到x的最长距离,x.su是次长距离。

x.fd表示从x到某个后代的最长距离,x.sd是次长距离。

求上面的那四个东西只要统计son.fu+f[son]和g[son]+son.fd,求最长和次长。

如果x.fu和x.fd不重复,自然是x.fu+x.fd最长

否则最长为max{x.fu+x.sd,x.su+x.fd}

这样又一个递归,可以O(n)求出。

取个最大值,就是答案了。


代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n;
struct EDGE
{
int to;
EDGE* las;
} e[200000];//前向星存边
EDGE* last[100001];
int d[100001];//d[x]为x的度
long long ans;
long long f[100001],sum[100001],g[100001];//sum[x]=sum{f[son]}用于省去dfs2中算f[brother]之和的部分
void dfs1(int,int);//求f
void dfs2(int,int);//求g
struct First_and_Second
{
long long fu;
int nfu;//这个是fu的编号,用于判断重复
long long fd;
int nfd;//这个是fd的编号,用于判断重复
long long su,sd;
//次大的编号是没有必要标的,因为不需判断fu与sd或su与fd重复,不然fu就不会与fd重复,不影响答案
} s[100001];
void dfs3(int,int);//求答案
int main()
{
freopen("rw.in","r",stdin);
freopen("rw.out","w",stdout);
scanf("%d",&n);
int i,j=-1,x,y;
for (i=1;i<n;++i)
{
scanf("%d%d",&x,&y);
++d[x];
++d[y];
e[++j]={y,last[x]};
last[x]=e+j;
e[++j]={x,last[y]};
last[y]=e+j;
}
dfs1(0,1);
dfs2(0,1);
dfs3(0,1);
printf("%lld.00000\n",ans);
return 0;
}
void dfs1(int fa,int x)
{
EDGE* ei;
for (ei=last[x];ei;ei=ei->las)
if (ei->to!=fa)
{
dfs1(x,ei->to);
sum[x]+=f[ei->to];
}
f[x]=d[x]+sum[x];//方程原因见上
}
void dfs2(int fa,int x)
{
EDGE* ei;
for (ei=last[x];ei;ei=ei->las)
if (ei->to!=fa)
{
g[ei->to]=d[x]+g[x]+sum[x]-f[ei->to];//方程原因见上。
dfs2(x,ei->to);
}
}
void dfs3(int fa,int x)
{
EDGE* ei;
for (ei=last[x];ei;ei=ei->las)
if (ei->to!=fa)
{
dfs3(x,ei->to);
if (s[ei->to].fu+f[ei->to]>s[x].fu)//和最大作比较
{
s[x].su=s[x].fu;
s[x].fu=s[ei->to].fu+f[ei->to];
s[x].nfu=ei->to;
}
else if (s[ei->to].fu+f[ei->to]>s[x].su)//和次大作比较
s[x].su=s[ei->to].fu+f[ei->to];
if (g[ei->to]+s[ei->to].fd>s[x].fd)//同上
{
s[x].sd=s[x].fd;
s[x].fd=g[ei->to]+s[ei->to].fd;
s[x].nfd=ei->to;
}
else if (g[ei->to]+s[ei->to].fd>s[x].sd)//同上
s[x].sd=g[ei->to]+s[ei->to].fd;
}
if (s[x].nfu!=s[x].nfd)
ans=max(ans,s[x].fu+s[x].fd);
else
ans=max(ans,max(s[x].fu+s[x].sd,s[x].su+s[x].fd)); //原因见上
//有的人可能担心nfu和nfd恰好一样,但可能还会有等于fu或fd的路程。实际上,如果有这种可能,那么有su=fu或sd=fd,不会影响答案。
//如果x只有一个儿子,那么必有nfu==nfd,由于su和sd为0,所以不会影响答案。
}

【NOIP2016提高A组集训第14场11.12】随机游走——期望+树形DP的更多相关文章

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

    题目 YJC最近在学习图的有关知识.今天,他遇到了这么一个概念:随机游走.随机游走指每次从相邻的点中随机选一个走过去,重复这样的过程若干次.YJC很聪明,他很快就学会了怎么跑随机游走.为了检验自己是不 ...

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

    题目描述 YJC最近在学习图的有关知识.今天,他遇到了这么一个概念:随机游走.随机游走指每次从相邻的点中随机选一个走过去,重复这样的过程若干次.YJC很聪明,他很快就学会了怎么跑随机游走.为了检验自己 ...

  3. 【JZOJ4889】【NOIP2016提高A组集训第14场11.12】最长公共回文子序列

    题目描述 YJC最近在学习字符串的有关知识.今天,他遇到了这么一个概念:最长公共回文子序列.一个序列S,如果S是回文的且分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已 ...

  4. 【JZOJ4888】【NOIP2016提高A组集训第14场11.12】最近公共祖先

    题目描述 YJC最近在学习树的有关知识.今天,他遇到了这么一个概念:最近公共祖先.对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. ...

  5. JZOJ 【NOIP2016提高A组集训第16场11.15】兔子

    JZOJ [NOIP2016提高A组集训第16场11.15]兔子 题目 Description 在一片草原上有N个兔子窝,每个窝里住着一只兔子,有M条路径连接这些窝.更特殊地是,至多只有一个兔子窝有3 ...

  6. JZOJ 【NOIP2016提高A组集训第16场11.15】SJR的直线

    JZOJ [NOIP2016提高A组集训第16场11.15]SJR的直线 题目 Description Input Output Sample Input 6 0 1 0 -5 3 0 -5 -2 2 ...

  7. 【JZOJ4893】【NOIP2016提高A组集训第15场11.14】过河

    题目描述 数据范围 解法 由于同一个点,同一个圆盘最多只会走一次. 把(i,j)当作一个点,表示第i个点,放第i个圆盘. 那么就可以使用最短路. 时间复杂度为O(n4∗k). 事实上存在冗余圆盘,一个 ...

  8. 【NOIP2016提高A组集训第4场11.1】平衡的子集

    题目 夏令营有N个人,每个人的力气为M(i).请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法? 分析 如果暴力枚举每个人被分到哪 ...

  9. 【JZOJ4841】【NOIP2016提高A组集训第4场11.1】平衡的子集

    题目描述 夏令营有N个人,每个人的力气为M(i).请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法? 数据范围 40%的数据满足: ...

随机推荐

  1. Java 基础 - 原生类型

    更详细的说明,请参考: Java 原生类型与包装器类型深度剖析,https://blog.csdn.net/justloveyou_/article/details/52651211 一. 原生类型与 ...

  2. Jupyter NoteBook输出的图表太小看不清怎么办?

    如果使用的是matplotlib绘图,可以通过以下命令更改图片的大小: %matplotlib linline 如果是 plt.figure(figsize=(5,3)) #其中(5, 3)用于控制图 ...

  3. 共享商业&技术红利,阿里云SaaS加速器让天下没有难做的SaaS

    9月26日,阿里云在2019杭州云栖大会上发布了SaaS加速器3.0版“一云多端”多个应用平台,展示了阿里云给伙伴带来的多种商业和技术红利.阿里云SaaS加速器将帮助伙伴做好SaaS,卖好SaaS:帮 ...

  4. Nacos v0.7.0:对接CMDB,实现基于标签的服务发现能力

    Nacos近期发布了0.7.0版本,该版本支持对接第三方CMDB获取CMDB数据.使用Selector机制来配置服务的路由类型.支持单机模式使用MySQL数据库.上线Node.js客户端,并修复了一些 ...

  5. luoguP2398 GCD SUM [gcd]

    题目描述 for i=1 to n for j=1 to n sum+=gcd(i,j) 给出n求sum. gcd(x,y)表示x,y的最大公约数. 输入输出格式 输入格式: n 输出格式: sum ...

  6. DNS的解析过程

    1.什么是DNS 在互联网上,唯一标识一台计算机的是IP地址,但是IP地址不方便记忆,通过一个域名对应一个IP地址,来达到找到IP地址的目的,那么DNS就是将域名转换成IP地址的过程. 2.DNS查询 ...

  7. H2数据库的基本使用

    文章目录 下载jar包 启动服务 下载jar包 下载h2-1.3.176.jar 这个包(部分服务版本不一致,请自行更换版本) 启动服务 从终端定位到刚才jar包下载的位置,比如我这里是Downloa ...

  8. Jenkins 自动部署

      一.安装插件[系统管理 → 插件管理 ] 为了通过SSH上传war包,我们需要安装Publish Over SSH 插件. 二.添加SSH 服务器[系统管理→系统设置] 参数说明: Name:ss ...

  9. 微信小程序 主题皮肤切换(switch开关)

    示例效果: 功能点分析: 1.点击switch开关,切换主题皮肤(包括标题栏.底部tabBar):2.把皮肤设置保存到全局变量,在访问其它页面时也能有效果3.把设置保存到本地,退出应用再进来时,依然加 ...

  10. 最近开始学习python,学习到了关于web的内容。

    然而在win10中IIS发布CGI脚本的时候遇到了各种各样的问题. 如ISAPI和CGI限制,权限限制等等,一一的百度解决了,最后又出现了 HTTP 错误 502.2 - Bad Gateway Th ...