Advent of Code 2024 - Day 23LAN Party
| Problem statement | Source code | Tags: Graph theory
This problem pays tribute to 2016 day 9 (unimplemented).
First we can conceptually understand what the two parts are asking for. The first part enumerates the triangles (cliques of size 3) in the graph, looking for ones that contain one node starting with t; the second part finds the maximum clique (largest maximal clique). This is extremely trivial if OCaml has a library as powerful as networkx:
But since there is not (I often talk about "reward of a good language choice is you can cheat"; maybe this is "punishment of a bad language choice"? :)), we have to implement these algorithms ourselves.
Part 1
I build the graph as a normal adjacency list with bidirectional edges.
A triangle is defined by one node plus an edge between two of its neighbors. So we can iterate over all (node, edge) pairs, and check if the edge's endpoints are neighbors of the node. This is , which is better than the naïve .
Each triangle is counted 6 times, once for each corner, and twice for each edge in both directions, so the answer is !triangles / 6.
Part 2
I drew the graph with networkx and it looks like this:

While not immediately clear, I guess it gives some sense of the problem structure and scale? :)
Here's comes the real challenge: finding the maximum clique. I chose Bron–Kerbosch with pivoting. I'm not going to explain exactly how it works, since it's all on Wikipedia. I just aim to implement the following pseudocode:
As for choosing the pivot, Wikipedia says "chosen to minimize the number of recursive calls made by the algorithm". The heuristic is to choose the pivot such that is as small as possible—i.e., choose that maximizes .
Because I'm not interested in all maximal cliques, just the largest one, each time I find a maximal clique, I check if it's larger than the best one found so far. I also implemented a pruning condition: if the size of the current clique plus the number of remaining candidates can never beat the current best, I stop searching that branch. The following is a faithful implementation of the above algorithm.