When caching the alive ancestors/descendants, we were not merging the alive sets found in different paths. The consequence was that a vertex that had already been visited in the same find_alive call would have its set of alive ancestors overwritten on the second visit. But since that vertex is marked as visited on the first visit, the second visit has no alive ancestors, and the alive ancestor set would therefore end up empty.
After careful benchmarking, caching all the vertices on real-world examples doesn't bring much benefit, and may even slow things down significantly.
PNKAJTFZM37FD6XPC3HLVBDT54XDC3SQMFNM32N6TTZ72BVFUKWQC
JQR4Q2NKNPVEWUWDTV55HXSDVYVYFEO5V4OG3XNAXC4HD6OVOH7QC
7NSTS6PKVQWNUGIUYBRS4GWHJPAV57TOPBTDCOBZ5YYQNFZIZW2QC
VO5OQW4W2656DIYYRNZ3PO7TQ4JOKQ3GVWE5ALUTYVMX3WMXJOYQC
SXEYMYF7P4RZMZ46WPL4IZUTSQ2ATBWYZX7QNVMS3SGOYXYOHAGQC
RSFUX6MLPHII3DRELHN62DOJCHFCDNKSRMWJDSFGTWN5S4RJVSSQC
YN63NUZO4LVJ7XPMURDULTXBVJKW5MVCTZ24R7Z52QMHO3HPDUVQC