EDIT: I have read the code for the author solution for $$$M \leq 8$$$ and it is mostly in this style and includes a chunking like here and a similar case breakdown at the final chunk of size 3. I'd say all of the ideas here are a subset of the ideas in the full solution, though it also has one more clever element and a few more deails around it. I'll sum up the main clever part (as I understand it) at the end of the post.
I came up with this solution with $$$M \leq 11$$$ to the problem and noticed the best solution at the competition was with $$$M \leq 12$$$, so I decided to post about it. This solution is quite complicated (I also have a simpler scheme with $$$12$$$), so it is understandable that no one had time for it (and I imagine $$$M \leq 8$$$ is even harder and/or cleverer).
Here is a link to the problem: https://drive.google.com/file/d/1jMpszX2nPZ79jrK8yzDFIZXNb0CG_efi/view
First notice that we can keep a state of which two nodes are opposite ends of some diameter. Then on a given node, either both ends stay the same or one end moves to the new node and the other end remains.
We will solve the problem by splitting the $$$N$$$ nodes into some number of chunks. Each chunk will have a size $$$K_i$$$ and will allow up to $$$M_i$$$ messages. We want $$$\sum_i K_i = N$$$ and to minimize $$$M_i$$$.
The core idea is that each chunk will encode the updates to the state (which 2 nodes are ends of diameters) up to the end of the previous chunk (say of size $$$K$$$). Updates can be of the form:
- No update: 1 option.
- Overwrite one end: $$$2K$$$ options (we partition basedon whether we overwrite smaller or larger (by index) end).
- Overwrite both ends: $$$K (K - 1) / 2$$$ options.
Therefore the total number of updates for a "generic" chunk is $$$F(K) = 1 + 2K + K(K-1)/2$$$. We actually need only case 3 for the first chunk, since both ends must be in it (though this turns out not to be needed for my solution, since the linear term is quite small for the first chunk, which is very large).
A given "generic" chunk can encode $$$E(K, M) = \sum_j {K_i \choose j} 4^j$$$ options about the previous chunk. Therefore, we just want to maintain $$$E(K_{i + 1}, M_{i + 1}) \geq F(K_i)$$$ for all $$$i$$$.
However, we still have to deal with one issue -- no one encodes for the final chunk, so it has to encode for itself as well as the penultimate chunk, i.e. it needs a custom scheme.
We have such a custom scheme for $$$K=3$$$, $$$M=3$$$, which will encode for itself and a previous chunk of size $$$4$$$. There is one helpful observation: if an ends lies in the last chunks, we can skip encoding (part of) the state after the penultimate chunk.
Therefore, we just have the chunks $$$(K_i, M_i)$$$ in reverse order like so:
- $$$(3, 3)$$$: custom scheme for itself and the previous chunk.
- $$$(4, 3)$$$: $$$E(4, 3) = 369 \geq F(5) = 351$$$.
- $$$(25, 5)$$$: $$$E(25, 5) = 57795621 \geq F(9968) = 49695465$$$.
- $$$(9968, 0)$$$: we are done.
Finally, let us describe the custom scheme for the final chunk. Let the $$$3$$$ final nodes be $$$A, B, C$$$ and the previous $$$4$$$ be $$$X, Y, Z, W$$$.
- At $$$A$$$:
- If $$$A$$$ is an end:
- If 0 of $$$X, Y, Z, W$$$ are still ends: send $$$0$$$.
- If 1 of $$$X, Y, Z, W$$$ is still an end: send $$$1$$$.
- If $$$A$$$ is not an end:
- If 0 of $$$X, Y, Z, W$$$ are ends: send $$$2$$$.
- If 1 of $$$X, Y, Z, W$$$ is an end: send $$$3$$$.
- If 2 of $$$X, Y, Z, W$$$ are ends: send $$$4$$$.
- If $$$A$$$ is an end:
- At $$$B$$$:
- $$$A$$$ sent $$$0$$$ (we will know the full state after this):
- $$$B$$$ is an end:
- Together with $$$A$$$: send $$$0$$$.
- Overwrites $$$A$$$ which overwrote the smaller end: send $$$1$$$.
- Overwrites $$$A$$$ which overwrote the larger end: send $$$2$$$.
- $$$B$$$ is not an end:
- $$$A$$$ overwrote the smaller end: send $$$3$$$.
- $$$A$$$ overwrote the larger end: send $$$4$$$.
- $$$B$$$ is an end:
- $$$A$$$ sent $$$1$$$:
- $$$B$$$ is an end together with $$$A$$$ (we will know the full state after this): send $$$0$$$.
- $$$B$$$ is not an end or $$$B$$$ overwrites $$$A$$$: send $$$1-4$$$ to encode which of $$$X, Y, Z, W$$$ is an end.
- $$$A$$$ sent $$$2$$$ (we will know the full state after this):
- $$$B$$$ is not an end: send $$$0$$$.
- $$$B$$$ overwrites the smaller end: send $$$1$$$.
- $$$B$$$ overwrites the larger end: send $$$2$$$.
- $$$A$$$ sent $$$3$$$:
- $$$B$$$ overwrites the $$$X, Y, Z, W$$$ end: send $$$0$$$.
- $$$B$$$ is not an end or $$$B$$$ is an end together with the $$$X, Y, Z, W$$$ end: send $$$1-4$$$ to encode which of $$$X, Y, Z, W$$$ is an end.
- $$$A$$$ sent $$$4$$$:
- $$$B$$$ is an end:
- With $$$X$$$ or $$$Y$$$: send $$$0$$$.
- With $$$Z$$$ or $$$W$$$: send $$$1$$$.
- $$$B$$$ is not an end:
- The ends are $$$X-Y$$$ or $$$X-W$$$: send $$$2$$$.
- The ends are $$$Y-Z$$$ or $$$Y-W$$$: send $$$3$$$.
- The ends are $$$X-Z$$$ or $$$Z-W$$$: send $$$4$$$.
- $$$B$$$ is an end:
- $$$A$$$ sent $$$0$$$ (we will know the full state after this):
- At $$$C$$$:
- If we know the full state up to now:
- $$$C$$$ is not an end: send $$$0$$$.
- $$$C$$$ overwrites the smaller end: send $$$1$$$.
- $$$C$$$ overwrites the larger end: send $$$2$$$.
- $$$A$$$ sent $$$1$$$ and $$$B$$$ sent $$$1-4$$$:
- $$$C$$$ is an end with the $$$X, Y, Z, W$$$ end: send $$$0$$$.
- $$$B$$$ is an end with the $$$X, Y, Z, W$$$ end: send $$$1$$$.
- $$$A$$$ is an end with the $$$X, Y, Z, W$$$ end: send $$$2$$$.
- $$$C$$$ is an end with $$$B$$$: send $$$3$$$.
- $$$C$$$ is an end with $$$A$$$: send $$$4$$$.
- $$$A$$$ sent $$$3$$$ and $$$B$$$ sent $$$0$$$:
- $$$C$$$ is an end:
- $$$C$$$ is an end $$$B$$$: send $$$0$$$.
- $$$C$$$ overwrites $$$B$$$ which overwrote the smaller end: send $$$1$$$.
- $$$C$$$ overwrites $$$B$$$ which overwrote the larger end: send $$$2$$$.
- $$$C$$$ is not an end:
- $$$B$$$ overwrote the smaller end: send $$$3$$$.
- $$$B$$$ overwrote the smaller end: send $$$4$$$.
- $$$C$$$ is an end:
- $$$A$$$ sent $$$3$$$ and $$$B$$$ sent $$$1-4$$$:
- $$$C$$$ is an end with the $$$X, Y, Z, W$$$ end: send $$$0$$$.
- $$$B$$$ is an end with the $$$X, Y, Z, W$$$ end: send $$$1$$$.
- $$$C$$$ is an end with $$$B$$$: send $$$2$$$.
- $$$C$$$ and $$$B$$$ are not ends:
- The $$$X, Y, Z, W$$$ end overwrote the smaller end: send $$$3$$$.
- The $$$X, Y, Z, W$$$ end overwrote the smaller end: send $$$4$$$.
- $$$A$$$ sent $$$4$$$ and $$$B$$$ sent $$$0-1$$$:
- $$$C$$$ is an end with $$$B$$$: send $$$0$$$.
- $$$C$$$ is not an end:
- The other end is $$$X$$$ or $$$Z$$$: send $$$1$$$.
- The other end is $$$Y$$$ or $$$W$$$: send $$$2$$$.
- $$$C$$$ is an end and $$$B$$$ is not:
- The other end is $$$X$$$ or $$$Z$$$: send $$$3$$$.
- The other end is $$$Y$$$ or $$$W$$$: send $$$4$$$.
- $$$A$$$ sent $$$4$$$ and $$$B$$$ sent $$$2-4$$$:
- $$$C$$$ is not an end: Each case for what $$$B$$$ sent has 2 options for the ends -- encode which by sending $$$0$$$ or $$$1$$$.
- $$$C$$$ is an end: Each case for what $$$B$$$ sent has 3 possible nodes as ends -- encode which of those is an end with $$$C$$$ by sending $$$2$$$, $$$3$$$ or $$$4$$$.
- If we know the full state up to now:
EDIT: Seems like the core idea of the full solution with 8 messages is to not keep the state fully defined between chunks, but insead keep 4 possible candidates per end. This lets us cover multiple possible updates with the same configuration, thus using fewer messages/expanding the chunks faster. The key part is that the final 3 nodes can additionally resolve this ongoing ambiguity if they need to (i.e. if no update overwrote it in the penultimate or final chunk) -- this happens through a slightly more efficient scheme than mine and/or exploiting the cases that are not tight in my scheme.



