Simon Tatham 3dbd97b60f Rewrite findloop.c for a simpler variant of Tarjan's algorithm.
Thanks to Amir Livne Bar-on, who implemented this variant from a
description posted in the Mastodon thread following up my recent blog
post about loop-finding.

The revised algorithm has the same asymptotic complexity as the one I
already had. But it has better constant factors, and less code: it can
run in a single depth-first pass over the graph instead of three
separate passes, and it needs to store fewer variables per vertex.

This version relies on the insight that if you DFS over an undirected
graph and imagine it constructing a rooted spanning forest with each
component's tree rooted at whatever vertex you started that component
from, then every edge that the DFS visits without making it part of
the spanning forest must join a vertex to one of its direct ancestors
in that component's tree.

(Because the other options are that it joins the DFS's current vertex
to one the search hasn't visited at all yet – in which case the DFS
_would_ follow it, and make it a forest edge after all. Or else it
joins this vertex to a cousin in an earlier finished subtree – but
then when the DFS processed that subtree, it would have explored the
same edge in the other direction, and added our current vertex to that
subtree, which by assumption it didn't.)

Hence, instead of assigning every vertex a distinct integer label and
calculating the min/max label reachable from each subtree, we can
instead assign each vertex its tree depth, and simply calculate the
minimum _depth_ of vertex reachable from each subtree: if a subtree
starting at depth D can reach a vertex at depth <D, it's because
there's one of those non-tree edges to a vertex outside the subtree,
so the tree edge entering the subtree isn't a bridge.

And since every non-tree edge must point to a vertex we've already
seen (and hence assigned a depth to), this can be done in the same
pass as calculating the depths in the first place - and we don't even
need to _store_ the spanning forest we generate.
2024-09-27 13:29:44 +01:00
2023-07-14 08:31:44 +01:00
2024-01-02 23:34:28 +00:00
2021-04-25 09:59:15 +01:00
2024-08-16 07:48:02 +01:00
2023-04-20 18:42:50 +01:00
2023-01-15 20:59:22 +00:00
2023-03-26 20:32:38 +01:00
2024-01-02 23:34:28 +00:00
2017-09-20 18:03:44 +01:00
2023-06-11 00:33:27 +01:00
2021-03-29 19:02:23 +01:00
2023-08-13 16:44:24 +01:00
2018-11-13 21:48:24 +00:00
2023-06-11 00:33:27 +01:00
2024-09-27 13:29:44 +01:00
2017-05-07 16:25:56 +01:00

This is the README accompanying the source code to Simon Tatham's
puzzle collection. The collection's web site is at
<https://www.chiark.greenend.org.uk/~sgtatham/puzzles/>.

The puzzle collection is built using CMake <https://cmake.org/>. To
compile in the simplest way (on any of Linux, Windows or Mac), run
these commands in the source directory:

  cmake .
  cmake --build .

The manual is provided in Windows Help format for the Windows build;
in text format for anyone who needs it; and in HTML for the Mac OS X
application and for the web site. It is generated from a Halibut
source file (puzzles.but), which is the preferred form for
modification. To generate the manual in other formats, rebuild it,
or learn about Halibut, visit the Halibut website at
<https://www.chiark.greenend.org.uk/~sgtatham/halibut/>.
Description
No description provided
Readme 26 MiB
Languages
C 93.3%
JavaScript 1.4%
Objective-C 1.1%
CMake 1.1%
HTML 0.8%
Other 2.2%