[Tutorial] Diameter of a tree and its applications

Revision en10, by TheScrasse, 2022-03-26 20:34:07

Hello everyone,
finding the diameter is one of the most frequent ways to solve problems about trees. In this tutorial we will see how to find a diameter and some of its properties, and we will use them to solve some problems of increasing difficulty.
The first part of the tutorial is quite basic, so feel free to skip it and jump to the problems if you already know the concepts.

Target: rating $[1400, 2300]$ on CF
Prerequisites: basic graph theory, greedy

## The diameter

Given an unweighted tree, let's define $\text{dist}(a, b) =$ the number of edges in the simple path $a \rightarrow b$.

A diameter of the tree $a \rightarrow b$ is the longest path, i.e., the one that maximizes $\text{dist}(a, b)$ over all pairs of nodes. If there are multiple diameters, let's pick any of them.

The same definition is valid for a weighted tree with nonnegative weights (with $\text{dist}(a, b) =$ the sum of the weights of the edges in the simple path $a \rightarrow b$).

#### Finding a diameter

Given a tree with $n$ nodes are multiple ways to find a diameter. Here is one of the simplest ways:

Run a DFS from any node $p$. Let $a$ be a node whose distance from node $p$ is maximized. Run another DFS from node $a$. Let $b$ be a node whose distance from node $a$ is maximized. $a \rightarrow b$ is a diameter.

#### Tree = edges of a diameter + forest

Before proving the previous algorithm, let's analyze the structure of the tree (we will mention the diameter, but we will not use the fact that $a \rightarrow b$ is actually a diameter before proving it).

We started a DFS from node $p = 16$, and we got that node $a = 1$ is the farthest from $p$, and node $b = 7$ is the farthest from $a$.

Let's represent the diameter on a line. If you remove the edges of the diameter, you get a forest (i.e., several trees). Let's root each tree at the node in the diameter. What's the height (i.e., the maximum distance from the root to any node) of each component?

Let $q$ be the root of the component of $p$. Let's consider any component whose root $d$ is between $a$ (included) and $q$ (excluded), and one of its nodes $c$.

We get

$\text{dist}(p, a) \geq \text{dist}(p, c) \implies \text{dist}(p, a) - \text{dist}(p, d) \geq \text{dist}(p, c) - \text{dist}(p, d) \implies \text{dist}(a, d) \geq \text{dist}(c, d)$.

In other words, the height of each component with root in the left half of the diameter (i.e., $\text{dist}(a, d) < \text{dist}(d, b)$) is at most the distance of the root of the component from the left end of the diameter.

You can prove the same statement for the right half of the diameter (i.e., $\text{dist}(a, d) \geq \text{dist}(d, b)$), using that $b$ is the farthest node from $a$.

#### Farthest node for each node

For each node $i$, let's find a node $j$ such that $\text{dist}(i, j)$ is maximum.

Claim: $j = a$ or $j = b$ always works.

Proof:

• If $j = j_1$ works ($j_1$ is not in the same component of $i$; let's assume without loss of generality that $j_1$ is closer to $a$ than to $b$), $\text{dist}(i, j_1) = \text{dist}(i, r) + \text{dist}(r, j_1) \leq \text{dist}(i, r) + \text{dist}(r, a) = \text{dist}(i, a)$. Then, $j = a$ also works.
• If $j = j_2$ works ($j_2$ is in the same component of $i$), $\text{dist}(i, j_1) \leq \text{dist}(i, r) + \text{dist}(r, j_1) \leq \text{dist}(i, r) + \text{dist}(r, a) = \text{dist}(i, a)$. Then, $j = a$ also works.

#### Proof that $a \rightarrow b$ is a diameter

Now we can finish the proof.

Suppose that $u \rightarrow v$ is a diameter. We have either $\text{dist}(u, a) \geq \text{dist}(u, v)$ or $\text{dist}(u, b) \geq \text{dist}(u, v)$ (see "Farthest node for each node").

Let's assume without loss of generality that $\text{dist}(u, b) \geq \text{dist}(u, v)$. We get $\text{dist}(a, b) \geq \text{dist}(u, b) \geq \text{dist}(u, v)$, so $a \rightarrow b$ is a diameter.

#### Observations

The algorithm also works in a weighted tree with positive edges (we've never used that the weights are $1$).

However, it doesn't work on general graphs (discussion).

## How to use the diameter

Most of the times, spamming "the farthest node from each node is one end of the diameter" and "the height of each component is smaller than the distance to the closest end of the diameter" is enough to reduce the problem to something simpler.

Find a diameter $a \rightarrow b$ (from now, $a \rightarrow b$ will always be a diameter, unless otherwise stated). Now, you may need to consider any path of the tree. There are two cases: the path intersects (blue) or doesn't intersect (green) the diameter.

Then, you may wonder how to make the path longer / "more optimal" / etc. according to the statement. For example, you may need to use $\text{dist}(7, 5) \geq \text{dist}(5, 19)$ to show that $8 \rightarrow 7$ is "more optimal" than $8 \rightarrow 19$.

## 1004E - Sonya and Ice Cream (rating: 2400)

Hint 1
Hint 2
Hint 3
Solution

Implementation by nor (C++): 151009669

## 633F - The Chocolate Spree (rating: 2600)

Hint 1
Hint 2
Hint 3
Solution

Implementation by nor (C++): 151018941

## 1434D - Roads and Ramen (rating: 2800)

Hint 1
Hint 2
Hint 3
Hint 4
Hint 5
Solution

Implementation by nor (C++): 151024814

## Other problems

CSES — Tree Distances I (to check your implementation) (suggested by nor)
102694B - Dynamic Diameter
abc221_f
IOI 2013 — Dreaming (timreizin)
USACO 2018 — New Barns (Olympia)
CEOI 2019 — Dynamic Diameter (hard) (nor)

## Conclusions

We've seen that finding a diameter can also solve seemingly unrelated problems, and it's a good candidate idea if the problem involves a tree and maximum lengths/distances.

Of course, suggestions/corrections are welcome. In particular, please share in the comments other problems where you have to use the diameter.

I hope you enjoyed the blog!

#### History

Revisions

Rev. Lang. By When Δ Comment
en23 TheScrasse 2023-01-31 00:54:49 4
en22 TheScrasse 2022-03-29 08:34:20 53 Tiny change: '6])<br>\n[C' -> '6])<br>\n[problem:1214H] \([user:Irvideckis])<br>\n[C'
en21 TheScrasse 2022-03-28 19:43:58 107 Tiny change: '22-03-26])\n[RMI 202' -> '22-03-26])<br>\n[RMI 202'
en20 TheScrasse 2022-03-28 15:25:51 46 Tiny change: '8])<br>\n[C' -> '8])<br>\n[problem:456E] \([user:Ajam])<br>\n[C'
en19 TheScrasse 2022-03-28 14:01:48 50 Tiny change: '6])<br>\n[C' -> '6])<br>\n[problem:734E] \([user:preet_25])<br>\n[C'
en18 TheScrasse 2022-03-27 18:35:51 151
en17 TheScrasse 2022-03-27 01:21:02 174
en16 TheScrasse 2022-03-26 22:11:22 2 Tiny change: '])<br>\n[agc117_d](ht' -> '])<br>\n[arc117_d](ht'
en15 TheScrasse 2022-03-26 22:11:01 12 Tiny change: 'em:1404B] ([user:fla' -> 'em:1404B] \([user:fla' (published)
en14 TheScrasse 2022-03-26 22:10:33 133 (saved to drafts)
en13 TheScrasse 2022-03-26 21:29:13 107
en12 TheScrasse 2022-03-26 20:54:37 2 Tiny change: '\n[agc033_g](https://' -> '\n[agc033_c](https://'
en11 TheScrasse 2022-03-26 20:54:11 102
en10 TheScrasse 2022-03-26 20:34:07 30 Tiny change: '_dreaming)<br>\n[US' -> '_dreaming) ([user:timreizin])<br>\n[US'
en9 TheScrasse 2022-03-26 20:32:56 4 Tiny change: '22-03-26])\n[problem' -> '22-03-26])<br>\n[problem'
en8 TheScrasse 2022-03-26 20:32:28 78
en7 TheScrasse 2022-03-26 20:29:56 148
en6 TheScrasse 2022-03-26 19:13:45 123
en5 TheScrasse 2022-03-26 17:47:13 74 Tiny change: 'user:nor] (C++): [su' -> 'user:nor] \(C++): [su'
en4 TheScrasse 2022-03-26 17:28:06 1 Tiny change: '022-03-26]\n\nConclu' -> '022-03-26])\n\nConclu'
en3 TheScrasse 2022-03-26 17:27:42 255 Tiny change: '/abc221_f)\n[CEOI 20' -> '/abc221_f)<br>\n[CEOI 20'
en2 TheScrasse 2022-03-26 15:13:29 2 Tiny change: 'um lengths / distances.' -> 'um lengths/distances.'
en1 TheScrasse 2022-03-26 15:11:38 12115 Initial revision (published)