\chapter{树} \section{树的概念} \begin{definition} \newnoun{树}{tree}是一张无圈连通图。 在树中,度为1的顶点称为\newnoun{叶}{leaf},度不小于2的顶点称为\newnoun{内点}{branch node}。 树的集合称为\newnoun{林}{forest}。 \newnoun{平凡树}{trivial tree}是只有一个顶点、无边的树。 \end{definition} \begin{theorem} 对于$T=(V,E)$,下列叙述等价: \begin{enumerate} \item $T$是一棵树,即其连通且无圈; \item $T$连通,但删去任何一条边都会使它变为不连通的图; \item $T$无圈,但是添加任意一条边都会使它有圈; \item $T$中的任意一对顶点都有唯一的一条路相连; \item $T$连通,且$\vert E \vert = \vert v \vert - 1$; \item $T$无圈,且$\vert E \vert = \vert v \vert - 1$。 \end{enumerate} \end{theorem} \begin{definition} 对$G$中的一条边$e$,若$c(G-e) > c(G)$则称$e$为图$G$的一个\newnoun{桥}{bridge}。 \end{definition} \begin{theorem} 任意连通图都有生成树。 \end{theorem} \begin{remark} 同一个连通图可能有多个不同的生成树。 \end{remark} \begin{figure}[H] \centering \subfloat[连通图$G$]{ \begin{tikzpicture}[scale=1.5] \draw node[circle, draw=black] (a) at (1,0) {}; \draw node[circle, draw=black] (b) at (-1,0) {}; \draw node[circle, draw=black] (c) at (0,1) {}; \draw node[circle, draw=black] (d) at (1,-1) {}; \draw node[circle, draw=black] (e) at (-1,-1) {}; \draw (a)--(b)--(c)--(a)--(d)--(e)--(b)--(d); \end{tikzpicture} } \hspace{2cm} \subfloat[$G$的一种生成树]{ \begin{tikzpicture}[scale=1.5] \draw node[circle, draw=black] (a) at (1,0) {}; \draw node[circle, draw=black] (b) at (-1,0) {}; \draw node[circle, draw=black] (c) at (0,1) {}; \draw node[circle, draw=black] (d) at (1,-1) {}; \draw node[circle, draw=black] (e) at (-1,-1) {}; \draw (e)--(b)--(c)--(a)--(d); \end{tikzpicture} } \hspace{2cm} \subfloat[$G$的另一种生成树]{ \begin{tikzpicture}[scale=1.5] \draw node[circle, draw=black] (a) at (1,0) {}; \draw node[circle, draw=black] (b) at (-1,0) {}; \draw node[circle, draw=black] (c) at (0,1) {}; \draw node[circle, draw=black] (d) at (1,-1) {}; \draw node[circle, draw=black] (e) at (-1,-1) {}; \draw (e)--(b)--(a)--(c); \draw (b)--(d); \end{tikzpicture} } \end{figure} \section{生成一棵树} \begin{theorem} 任何至少有两顶点的树至少有两个叶子顶点。 \end{theorem} \begin{theorem} 利用一下方法生成一张图: \begin{enumerate} \item 开始于一个根节点。 \item 重复进行一下操作:对已有的图$G$,建立一个新的顶点(子顶点),并将这个顶点通过一条边与$G$中的一个顶点(父顶点)相连。 \end{enumerate} 通过上述过程生成的图是一棵树,且任何树都能通过上述过程得到。 \end{theorem} \begin{theorem} 任何$n$个顶点的树都有$n-1$条边。 \end{theorem} \begin{example} 一棵树有$n_2$个顶点的度为2,$n_3$个顶点度为3,……,$n_k$个顶点的度为$k$,问它有几片叶? \end{example} \begin{proof}[解] 设它有$n_1$片叶,则顶点数为$n_1 + n_2 + \dots + n_k$,那么它有$n_1 + n_2 + \dots + n_k - 1$条边。所有顶点的度的和为$n_1 + 2n_2 + \dots + kn_k$。根据握手定理, \[n_1 + 2n_2 + \dots + kn_k = 2(n_1 + n_2 + \dots + n_k - 1)\] 解得 \[n_1 = n_3 + 2n_4 + \dots + (k-2)n_k + 2\eqper\qedhere\] \end{proof} \section{树的计数} 首先我们需要区分\newnoun{无编号树}{unlabeled tree}与\newnoun{有编号树}{labeled tree}。 对于无编号树,下面两个图被认为是相同的无编号树: \begin{figure}[H] \centering \subfloat{ \begin{tikzpicture} \draw node[circle, draw=black] (a) at (18:2) {}; \draw node[circle, draw=black] (b) at (90:2) {}; \draw node[circle, draw=black] (c) at (162:2) {}; \draw node[circle, draw=black] (d) at (234:2) {}; \draw node[circle, draw=black] (e) at (306:2) {}; \draw (a)--(e)--(d)--(c); \draw (b)--(e); \end{tikzpicture} } \hspace{1cm} \subfloat{ \begin{tikzpicture} \draw node[circle, draw=black] (a) at (18:2) {}; \draw node[circle, draw=black] (b) at (90:2) {}; \draw node[circle, draw=black] (c) at (162:2) {}; \draw node[circle, draw=black] (d) at (234:2) {}; \draw node[circle, draw=black] (e) at (306:2) {}; \draw (a)--(e)--(b)--(c); \draw (d)--(b); \end{tikzpicture} } \caption{一组相同的无编号树} \end{figure} 而与之不同的是,下面的两个图被认为是不同的有编号树: \begin{figure}[H] \centering \subfloat{ \begin{tikzpicture} \draw node[circle, draw=black] (a) at (18:2) {1}; \draw node[circle, draw=black] (b) at (90:2) {2}; \draw node[circle, draw=black] (c) at (162:2) {3}; \draw node[circle, draw=black] (d) at (234:2) {4}; \draw node[circle, draw=black] (e) at (306:2) {5}; \draw (a)--(e)--(d)--(c); \draw (b)--(e); \end{tikzpicture} } \hspace{1cm} \subfloat{ \begin{tikzpicture} \draw node[circle, draw=black] (a) at (18:2) {1}; \draw node[circle, draw=black] (b) at (90:2) {2}; \draw node[circle, draw=black] (c) at (162:2) {3}; \draw node[circle, draw=black] (d) at (234:2) {4}; \draw node[circle, draw=black] (e) at (306:2) {5}; \draw (a)--(e)--(b)--(c); \draw (d)--(b); \end{tikzpicture} } \caption{一组不同的有编号树} \end{figure} \begin{theorem}[Cayley's Theorem]\label{Cayley's Theorem} $n$个顶点的有编号树的个数为$n^{n-2}$。 \end{theorem} \section{如何存储树} 如果想要证明定理\ref{Cayley's Theorem},我们需要先来考虑如何储存一棵树。 在这节中,我们将以下面的树为例考虑如何存储。 \begin{figure}[H] \centering \begin{tikzpicture} \draw node[circle, draw=black] (0) at (-2,0) {0}; \draw node[circle, draw=black] (1) at (4,1) {1}; \draw node[circle, draw=black] (2) at (0,0) {2}; \draw node[circle, draw=black] (3) at (-4,0) {3}; \draw node[circle, draw=black] (4) at (0,-2) {4}; \draw node[circle, draw=black] (5) at (4,-1) {5}; \draw node[circle, draw=black] (6) at (2,0) {6}; \draw node[circle, draw=black] (7) at (-1,4) {7}; \draw node[circle, draw=black] (8) at (1,4) {8}; \draw node[circle, draw=black] (9) at (0,2) {9}; \draw (3)--(0)--(2)--(6)--(1); \draw (5)--(6); \draw (4)--(2)--(9)--(8); \draw (9)--(7); \end{tikzpicture} \caption{一棵有编号树} \end{figure} 最普通的方法是利用它的\newnoun{邻接矩阵}{adjacency matrix}: \setcounter{MaxMatrixCols}{11} \begin{equation*} \begin{bNiceMatrix}[first-row,first-col] & 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9\\ 0 & 0 & 0 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\ 1 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\\ 2 & 1 & 0 & 0 & 0 & 1 & 0 & 1 & 0 & 0 & 1\\ 3 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 4 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 5 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\\ 6 & 0 & 1 & 1 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\ 7 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1\\ 8 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1\\ 9 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 1 & 1 & 0\\ \end{bNiceMatrix} \end{equation*} \setcounter{MaxMatrixCols}{10} 然而这明显收入了过多的无用信息(过多的零!)。 \subsection{The father code} 一个减少储存信息的自然的想法是:把0看作根节点,对于剩下的每个节点,只要记录下它的父节点是谁就足够描述这个图了。例如: \begin{table}[H] \centering \begin{tabular}{ccccccccc} 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9\\ 6 & 0 & 0 & 2 & 6 & 2 & 9 & 9 & 2 \end{tabular} \end{table} \subsection{The Prüfer code} 上面的father code显然已经比邻接矩阵要高效地多,而我们还有更好的方法。我们每次都从(不是根的)叶子中找到标号最小的那个,并记录下它的父亲,之后删除我们已经记录的这个叶子和边,重复操作直到只剩下根,于是我们得到了扩展的Prüfer code(extended Prüfer code): \begin{table}[H] \centering \begin{tabular}{ccccccccc} 1 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 2\\ 6 & 0 & 2 & 6 & 2 & 9 & 9 & 2 & 0 \end{tabular} \end{table} 首先,我们可以注意到,第二行的最后一个一定是零,因此它是多余的,对于一个$n$个端点的树,我们只需要$n-2$列。 实际上,在这个表格中,整个第一行也都是多余的: \begin{lemma} 扩展Prüfer code中的第二行可以确定第一行。 \end{lemma} \begin{proof} 如果我们只有第二行,且我们已经填好了前$n-1$位。现在,我们要考虑第$n$列的第一行的数:首先,第一行前面已经出现过的数不会填在这里,因为它们已经被删掉了;其次第二行中第$n$列及之后的数也不会填在这里,因为它们在之后还是父亲顶点,现在不可能作为叶子。这样我们就已经将范围缩小了;因为我们生成Prüfer code的规则要求我们每次都取编号最小的顶点,因此我们只要取不等于第一行已经出现过和第二行还未考虑到的数中最小的一个填入空格即可。 \end{proof} 在这里,我们可以看到$n-2$位的$n$元Prüfer code与$n$个顶点的树一一对应。由此,我们可以证明定理\ref{Cayley's Theorem}的正确性,因为Prüfer code 有$n^{n-2}$种。 \section{无编号树的数量} 至今我们还没有办法得知给定端点数的无编号树的数量的具体值。 \begin{theorem} 无编号$n$顶点树的数量$T_n$满足 \[\frac{n^{n-2}}{n} \leq T_n \leq \binom{2n-4}{n-2}\eqper\] \end{theorem} 为了证明这个定理,我们要先引入Planar code: 首先,我们先将无编号树``展平'',即使它的边互相不交叉。之后,我们从它的某个顶点旁边开始,使自己的右手边始终挨着树走一圈。那么,如果我们将我们第一次经过某个边记作1,第二次经过它记作0,那么我们就会得到一个序列1111100100011011010000。 \begin{figure}[H] \centering \begin{tikzpicture} \draw node[circle, draw=black, fill=black] (a) at (0,0) {}; \draw node[circle, draw=black] (b) at (0,2) {}; \draw node[circle, draw=black] (c) at (-2,2) {}; \draw node[circle, draw=black] (d) at (-4,2) {}; \draw node[circle, draw=black] (e) at (-6,2) {}; \draw node[circle, draw=black] (f) at (-8,2) {}; \draw node[circle, draw=black] (g) at (-4,4) {}; \draw node[circle, draw=black] (h) at (2,2) {}; \draw node[circle, draw=black] (i) at (2,4) {}; \draw node[circle, draw=black] (j) at (4,2) {}; \draw node[circle, draw=black] (k) at (4,4) {}; \draw node[circle, draw=black] (l) at (6,2) {}; \draw (f)--(e)--(d)--(c)--(b)--(h)--(j)--(l); \draw (d)--(g); \draw (b)--(a); \draw (h)--(i); \draw (j)--(k); \draw (j)--(l); \draw[dashed,-{Stealth[width=5pt]}] (-0.5,0)--(-0.5,1.5); \draw[dashed,-{Stealth[width=5pt]}] (-0.5,1.5)--(-8,1.5); \draw[dashed,-{Stealth[width=5pt]}] (-8,1.5) arc (-90:-270:0.5); \draw[dashed,-{Stealth[width=5pt]}] (-8,2.5)--(-4.5,2.5); \draw[dashed,-{Stealth[width=5pt]}] (-4.5,2.5)--(-4.5,4); \draw[dashed,-{Stealth[width=5pt]}] (-4.5,4) arc (-180:-360:0.5); \draw[dashed,-{Stealth[width=5pt]}] (-3.5,4)--(-3.5,2.5); \draw[dashed,-{Stealth[width=5pt]}] (-3.5,2.5)--(1.5,2.5); \draw[dashed,-{Stealth[width=5pt]}] (1.5,2.5)--(1.5,4); \draw[dashed,-{Stealth[width=5pt]}] (1.5,4) arc (-180:-360:0.5); \draw[dashed,-{Stealth[width=5pt]}] (2.5,4)--(2.5,2.5); \draw[dashed,-{Stealth[width=5pt]}] (2.5,2.5)--(3.5,2.5); \draw[dashed,-{Stealth[width=5pt]}] (3.5,2.5)--(3.5,4); \draw[dashed,-{Stealth[width=5pt]}] (3.5,4) arc (-180:-360:0.5); \draw[dashed,-{Stealth[width=5pt]}] (4.5,4)--(4.5,2.5); \draw[dashed,-{Stealth[width=5pt]}] (4.5,2.5)--(6,2.5); \draw[dashed,-{Stealth[width=5pt]}] (6,2.5) arc (90:-90:0.5); \draw[dashed,-{Stealth[width=5pt]}] (6,1.5)--(0.5,1.5); \draw[dashed,-{Stealth[width=5pt]}] (0.5,1.5)--(0.5,0); \draw[dashed,-{Stealth[width=5pt]}] (0.5,0) arc (0:-180:0.5); \end{tikzpicture} \end{figure} \begin{proof} Planar code 的第一位一定是1,最后一位一定是0,剩余$2n-4$位中有$n-2$(一半)是1,共有$\dbinom{2n-4}{n-2}$种,而有的Planar code不合法(例如11000110前五位有两个1却有三个0),因此$T_n < \dbinom{2n-4}{n-2}$,即右侧的不等式成立; 其次,对于一个无编号树,我们最多有$n!$种方法给他的不同节点编号成为不同的有编号树,因此无编号树的数量多于$\dfrac{n^{n-2}}{n!}$种,即$\dfrac{n^{n-2}}{n!} \leq T_n$。 \end{proof}