[Sdoi2013]直径

题目描述

小Q最近学习了一些图论知识。根据课本,有如下定义。树:无回路且连通的无向图,每条边都有正整数的权值来

表示其长度。如果一棵树有N个节点,可以证明其有且仅有N-1 条边。 路径:一棵树上,任意两个节点之间最多有一条简单路径。我们用 dis(a,b)表示点a和点b的路径上各边长度之和。称dis(a,b)为a、b两个节点间的距离。直径:一棵树上,最长的路径为树的直径。树的直径可能不是唯一的。

现在小Q想知道,对于给定的一棵树,其直径的长度是多少,以及有多少条边满足所有的直径都经过该边。

输入格式

第一行包含一个整数N,表示节点数。

接下来N-1行,每行三个整数a, b, c ,表示点 a和点b之间有一条长度为c的无向边。

2≤N≤200000,所有点的编号都在1..N的范围内,

边的权值≤10^9。

输出格式

共两行。第一行一个整数,表示直径的长度。第二行一个整数,表示被所有直径经过的边的数量。


我们首先证明一个定理:

给定一棵树,对于它的任一直径,若取其几何意义上的中点,叫做这条直径的中点。那么, 一棵树的所有直径的中点必定是同一点。

证明:

显然,当这棵树只有一条直径时,定理成立。但很多情况下一棵树不止一条直径。但所有直径必定都经过同一点。为 什么呢?(下面证明的过程中有关长度与距离之类的量都为几何意义上的量)

假设有两条直径不经过同一点。设两条直径分别有一点A,B,并且A能够在不经过这两条直径上的边的情况下到达B。 那么这两个节点就将所在的直径分成了两段。我们取每条直径上较长的那段,加上A和B之间的长度,显然大于原来的直径长度。

那么任意两条直径必定会相交于一点。现在再假设有两条直径满足它们的中点A,B不是同一点。显然对于中点来说, 它将其所在直径分成了相同长度的两段。不妨设有一条不经过直径的路径连接A和另一条直径上的C点,那么:A所在 直径长度的1/2 + E(A,C) + E(B,C) + B所在直径长度的1/2 ≥ 任意一条直径的长度 = A所在直径长度的1/2 + B所在直径 长度的1/2,这样就存在一条新的路径,其长度大于原来的直径,这有悖直径定义。

证毕。

回到直径这道题,我们可以先随便求一条直径出来,然后设法搞出它的中点(直径长度/2的位置)。现在有两种情况:

1.(软柿子)中点就是树的某个节点。我们可以直接以这个点为根进行计算。

2.中点在树的某条边上。酱紫的话就把这条边扔了,在剩下的两棵子树上计算。

怎么计算呢?

第一种情况,由于从根节点可以连接出许多棵子树。我们取出深度最大的三棵子树a,b,c,并用d[x]表示x子树的最大深度。

1.d[a] > d[b] > d[c]。显然直径会经过a子树和b子树。然后我们递归,在a子树和b子树的根上进行相同计算,算出直径必然经过的边。

2.d[a] > d[b] = d[c]。那么只需在a子树的根上进行相同计算即可。

3.d[a] = d[b] = d[c]。那么没有被所有直径经过的边。

如法炮制,对于第二种情况,我们只需在去掉边之后的两颗子树上分别进行上述操作即可。

猜你喜欢

转载自www.cnblogs.com/akura/p/10804844.html