题目链接

这的确是一道好题,我们不妨依循思路一步步推导,看问题是如何被解决的。

做一些约定,设$m$为树的叶子节点个数,设$len$为该树的直径(经过的点数)。

毫无疑问,直径可能有多条,我们需要把所有直径都破坏掉才能终止,但这些直径并不是毫无联系的。

引理:若$len$为奇数,则所有直径有同一个中点;若$len$为偶数,则所有直径有同一条最中间的边。

  • 至于证明,用反证法即可,大致就是如果存在两条直径的中点不是同一个,那就会产生更长的一条直径。

题目要求的终止状态就是不存在两个可以构成直径的点,可以构成直径的点指的是原先处在某一条直径的两端的点,我们可以先按$len$的奇偶讨论:

  1. 若$len$为奇数,即存在一个中点$x$,我们不妨将$x$设成根,不难发现,如果两个点$a,b$的$lca$是$x$,那$a,b$就能构成直径,否则就不能。这启发我们把所有可以构成直径的点,按照他们在$x$的哪个亲儿子下分组,那样同一个组内的点互相不能构成直径,不在一个组内的两点能构成直径。
  2. 若$len$为偶数,即所有直径都会经过中间两个点,我们模仿之前的思路,从这两个点之间分开,把这些可以构成直径的点分成的两个组,道理同上。

这样我们得到了若干个点的集合,假设我们得到了$t$个集合,其集合大小用$k$表示,所有集合大小之和用$sum$表示,并且我们只关心集合的大小,集合中具体有那些点并不重要。然后我们发现,如果存在两个集合都没有被完全染黑,原先的直径还是存在的,也就是说我们第一次使得只剩下一个集合没有被完全染黑的时间就是我们所希望的。

我们按照这个精简后的题目做,这里有两种做法,分别从两个不同角度求解。

法一:

在此之前,我们必须先明白一件事,期望实际上是若干个随机事件的概率乘上该事件的价值的和。

我们知道经过无限次染色后所有叶子终究都会被染黑,而每一种染黑的方案中这些叶子被染黑是有顺序的,由于每次染色都是随机的,所以产生每一种顺序的概率是均等的,但是不同的顺序会导致它们终止的时间不同。所以这个做法总体上是把所有事件按照点染黑的顺序分组分别算,最后把贡献加起来。

有诸多顺序它们的期望步数是相等的,我们会把它们合起来算。我们枚举一个集合,将它作为最后那个没有被完全染黑的集合,并枚举这个集合在终止时有多少个点已经被染黑了,显然所有满足以此为终止状态的顺序的期望步数都是一样的。这里要注意的是,染黑的最后一个点一定是其它集合中的点,这是需要特殊考虑的。

于是我们可以写出贡献和的表达式:

$$ans = \frac{1}{sum!} \sum_{i = 1}^{t} \sum_{j = 0}^{k_i - 1} \tbinom{k_i}{j} (m - k_i) (m - k_i + j - 1)! (k - j)! \sum_{z = k_i - j + 1}^{sum} \frac{m}{z}$$

这里可能有些需要解释的地方,就是为什么这么算是对的,这可能一开始看会觉得难以理解。你会发现对于每一个顺序而言,我们让$\sum_{z} \frac{m}{z}$成为它的贡献的行为令人费解,因为这个式子在做的东西是无序的,并没有按照我们所想的顺序染色。但是每个顺序的概率是均等的,我们仅仅只需要这个期望式子中的一部分,只要把$sum!$除掉就可以了。

法二:

既然我们要算的是所有合法事件的概率乘贡献之和(这里所说的合法事件指第一次使得只剩下一个集合没有被完全染黑,因为只有这些是被算进答案里的),用容斥也是可以得到的。

如果我们枚举一个集合$i$,想要让$i$成为最后那个没有被完全染黑的集合,我们算出只关心其余集合的点把它们染黑的期望时间。在这个期望中,每一种方案的最后一个染色的点一定不在$i$中。这里有两种情况,一种是在染色结束时$i$中仍存在没染黑的点,这属于合法情况;另一种是$i$中的点已经全部被染黑了,也就是所有点都没染黑了,这是需要去掉的。我们考虑每一种全部染黑的方案会在除了最后染色的集合外的其他$t-1$个集合中都被算到,所以最终的答案就是枚举每个集合算其余点被染黑的期望时间减去$t-1$倍的把所有点都染黑的期望时间。

我们发现这么容斥后,剩下的事件的概率和恰好是$1$,单纯从概率分支树上来讲肯定是对的。具体来讲就是一种全部染黑的方案事实上是一种合法方案的一个分支,本来就不应该算进去,而合法事件显然是不重复不遗漏的。

这是法二的实现:

#include <cstdio>
#include <algorithm> using namespace std; typedef long long LL; const int N = ;
const int MOD = ; int n, m, bt, len, su, ans, tmp;
int bl[N], inv[N], sui[N], dep[N], fa[N], deg[N]; int yu, la[N], to[N << ], pr[N << ];
inline void Ade(int a, int b) {
to[++yu] = b, pr[yu] = la[a], la[a] = yu;
} void Dfs(int x, int fat, int &c) {
dep[x] = dep[fa[x] = fat] + ;
if (dep[x] == len / ) ++c;
for (int i = la[x]; i; i = pr[i])
if (to[i] != fat) Dfs(to[i], x, c);
} inline int Add(int a, int b) {
return (a += b) >= MOD? a - MOD : a;
} int main() {
scanf("%d", &n);
for (int i = , x, y; i < n; ++i) {
scanf("%d%d", &x, &y);
Ade(x, y), Ade(y, x);
++deg[x], ++deg[y];
}
Dfs(, , tmp);
int rt = , tl = ;
for (int i = ; i <= n; ++i) {
if (dep[i] > dep[rt]) rt = i;
if (deg[i] == ) ++m;
}
Dfs(rt, , tmp);
for (int i = ; i <= n; ++i)
if (dep[i] > dep[tl]) tl = i;
len = dep[tl];
inv[] = , sui[] = m;
for (int i = ; i <= n; ++i) {
inv[i] = MOD - (LL)MOD / i * inv[MOD % i] % MOD;
sui[i] = Add(sui[i - ], (LL)m * inv[i] % MOD);
}
if (len & ) {
int md = -;
for (int i = tl; i; i = fa[i])
if (dep[i] == (len + ) / ) md = i;
dep[md] = ;
for (int i = la[md]; i; i = pr[i]) {
Dfs(to[i], md, tmp = );
if (tmp) bl[++bt] = tmp, su += bl[bt];
}
} else {
int m1 = -, m2 = -;
for (int i = tl; i; i = fa[i]) {
if (dep[i] == len / ) m1 = i;
if (dep[i] == len / + ) m2 = i;
}
dep[m2] = , Dfs(m1, m2, bl[++bt]);
dep[m1] = , Dfs(m2, m1, bl[++bt]);
su = bl[] + bl[];
}
for (int i = ; i <= bt; ++i)
ans = Add(ans, sui[su - bl[i]]);
ans = Add(ans, MOD - (bt - 1LL) * sui[su] % MOD);
printf("%d\n", ans);
return ;
}

【UOJ #351】新年的叶子(树的直径,期望)的更多相关文章

  1. [UOJ#351]新年的叶子

    [UOJ#351]新年的叶子 试题描述 躲过了AlphaGo 之后,你躲在 SingleDog 的长毛里,和它们一起来到了AlphaGo 的家.此时你们才突然发现,AlphaGo 的家居然是一个隐藏在 ...

  2. UOJ#351. 新年的叶子 概率期望

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ351.html 题目传送门 - UOJ351 题意 有一个 n 个节点的树,每次涂黑一个叶子节点(度为 1 ...

  3. uoj#351. 新年的叶子(概率期望)

    传送门 数学还是太差了,想了半天都没想出来 首先有一个定理,如果直径(这里考虑经过的点数)为奇数,所有直径有同一个中点,如果直径为偶数,所有直径有同一条最中间的边.这个可以用反证法,假设不成立的话直径 ...

  4. 「UOJ351」新年的叶子

    「UOJ351」新年的叶子 题目描述 有一棵大小为 \(n\) 的树,每次随机将一个叶子染黑,可以重复染,问期望染多少次后树的直径会缩小. \(1 \leq n \leq 5 \times 10^5\ ...

  5. HDU 4123(树的直径+单调队列)

    Bob’s Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  6. HDU 4612 Warm up(双连通分量缩点+求树的直径)

    思路:强连通分量缩点,建立一颗新的树,然后求树的最长直径,然后加上一条边能够去掉的桥数,就是直径的长度. 树的直径长度的求法:两次bfs可以求,第一次随便找一个点u,然后进行bfs搜到的最后一个点v, ...

  7. CF835F Roads in the Kingdom/UOJ126 NOI2013 快餐店 树的直径

    传送门--CF 传送门--UOJ 题目要求基环树删掉环上的一条边得到的树的直径的最小值. 如果直接考虑删哪条边最优似乎不太可做,于是考虑另一种想法:枚举删掉的边并快速地求出当前的直径. 对于环上的点, ...

  8. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

  9. 牛客网 桂林电子科技大学第三届ACM程序设计竞赛 G.路径-带条件的树的直径变形-边权最大,边数偶数的树上的最长路径-树形dp

    链接:https://ac.nowcoder.com/acm/contest/558/G 来源:牛客网 路径 小猫在研究树. 小猫在研究路径. 给定一棵N个点的树,每条边有边权,请你求出最长的一条路径 ...

随机推荐

  1. [HAOI2008]排名系统 & [Zjoi2006]GameZ游戏排名系统 BZOJ1862&BZOJ1056

    分析: 平衡树裸题,(学完LCT感觉自己不会普通的Splay了...),维护每个节点的权值大小顺序,和时间戳顺序,之后map维护一下是否存在过,(懒得写字符串hash了). 附上代码: #includ ...

  2. WPF编程,通过【帧】动态更改控件属性的一种方法。

    原文:WPF编程,通过[帧]动态更改控件属性的一种方法. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/detail ...

  3. ubuntu 12.04 桌面版关闭图形界面

    对于12.04的ubuntu桌面系统,如果想在开机的时候直接进入字符界面,那可以: 编辑文件 /etc/init/lightdm.conf,在第12行附近,原句“ and runlevel [!06] ...

  4. 【最详细最完整】在Linux 下如何打包免安装的QT程序?

    在Linux 下如何打包免安装的QT程序? 版权声明:嵌入式linux相关的文章是我的学习笔记,基于Exynos 4412开发板,一部分内容是总结,一部分是查资料所得,大家可以自由转载,但请注明出处! ...

  5. java.lang.IllegalStateException: Cannot forward after response has been committe

    参考:https://blog.csdn.net/lewky_liu/article/details/79845655 加上 return 搞定

  6. idea ssm项目迁移到另一台机器上时出现不能正常启动项目的解决方案

    首先右下角提示关联spring文件,关联之,然后启动,发现项目无法启动,然后开始排错 首先从这个日志里发现了这么一条提示信息 然后百度了一下,答案都是说 web.xml 之类的 spring拦截器问题 ...

  7. PowerBI开发 第五篇:关系和交互

    PowerBI 使用 内存的列式数据库 VertiPaq,用于对已发布的数据集进行数据压缩和快速处理,能够使PowerBI报表执行脱机访问,面向列的处理,高度优化对1:N关系的处理性能.关系是数据分析 ...

  8. 程序员大佬推荐的java学习路线

    作为我的第一篇博客,我第一个想到的就是在校时就看到的这篇文章.并且在之后的时间里自己都反复观看过,有时候这不单单是一篇学习路线,也是审视自己技术能力的里程碑,和激励自己的鞭挞绳. 先来个书籍清单: & ...

  9. [穷尽]ADO.NET连接字符串

    微软提供的四种数据库连接方式: System.Data.OleDb.OleDbConnection System.Data.SqlClient.SqlConnection System.Data.Od ...

  10. C#对战小游戏,持续更新(里面暂无内容,标记插眼)

    做的乱七八糟的 很明显的一点,对集合.数组.类的理解和运用   很差.很差.很差 今儿不做了,马德,头都肿大了 休息一下,捋一捋