Codeforces and Polygon may be unavailable from December 6, 19:00 (UTC) to December 6, 21:00 (UTC) due to technical maintenance. ×

Tutorial: The fastest tree algorithm, the XOR Linked Tree

Revision en1, by pajenegod, 2024-10-18 00:15:45

Hi Codeforces!

This is a blog about a really cool folklore technique that seems to have been forgotten over time. I currently only know of one place where it is mentioned on the internet, https://www.algonotes.com/en/minimal-memory-dp/ (from 2018), but I've been told that it is far older than this. I don't know a name for this technique, so I've decided to call it Xor Linked Tree, because of its close connection to XOR linked lists https://en.wikipedia.org/wiki/XOR_linked_list .

This is a technique for solving tree problems using very little time/memory. For example, every fastest solution in the "Tree Algorithms" section on https://cses.fi/problemset/ currently uses this technique. So it is blazingly fast, both in C++ and Python etc...

The idea: Suppose in the input of a problem, you are given a tree as n - 1 edges. To construct the XOR Linked Tree data-structure from this, you go through the list of edges and store the following two things for every node in the tree:

  1. deg[node] = The degree of the node.
  2. xor[node] = The XOR of all neighbours of node.

Storing this will only take $$$2 n$$$ integers, so it is very cheap memory wise. It is also very fast, because there are no .push_backs etc...

Claim: Using deg and xor, it is possible to reconstruct the tree.

Proof: Identify a leaf node in the tree (this can be done by finding a node with degree 1 in deg). Note that a leaf only has one neighbour, so the XOR of all of its neighbours is simply that neighbour. So the neighbour of a leaf is simply xor[leaf]. Now remove this leaf from the tree ("pluck it") by lowering the degree of its neighbour by one (deg[neighbour] -= 1) and XORing away leaf from xor[neighbour] (xor[neighbour] ^= leaf). Now we can just repeat this process of plucking leaves until there a single node left. We have now reconstructed the original tree.

This process ^ can easily be done with the following code ```py for node in range(n): while deg[node] == 1: nei = B[node]

Tags tree, traversal, xor, constant factor, memory limit, dfs, fast

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en39 English pajenegod 2024-10-20 23:13:06 1 Tiny change: 'rently uses this tech' -> 'rently use this tech'
en38 English pajenegod 2024-10-20 23:09:06 9 Tiny change: 's problem called Matchings https://d' -> 's problem "Matchings" https://d'
en37 English pajenegod 2024-10-20 23:08:34 124 Tiny change: '([see this](https://' -> '([see this for more information](https://'
en36 English pajenegod 2024-10-20 18:17:51 10
en35 English pajenegod 2024-10-19 14:16:01 47
en34 English pajenegod 2024-10-19 13:29:01 101 (published)
en33 English pajenegod 2024-10-18 23:22:01 415 Tiny change: 'xicPie9]. A big thanks to [user:' -> 'xicPie9]. Credit to [user:'
en32 English pajenegod 2024-10-18 23:11:09 32 Tiny change: ':9076307] from 201' -> ':9076307] by [user:Marcin_smu] from 201'
en31 English pajenegod 2024-10-18 23:06:04 12
en30 English pajenegod 2024-10-18 23:05:10 550 Tiny change: 'cy list | TBD | TBD | [243496' -> 'cy list | 2119 ms | 731.60 Mib | [243496'
en29 English pajenegod 2024-10-18 22:58:35 639
en28 English pajenegod 2024-10-18 02:53:10 30
en27 English pajenegod 2024-10-18 02:42:28 41
en26 English pajenegod 2024-10-18 02:41:41 4 Tiny change: 'is **yes**. It is possi' -> 'is **yes**, it is possi'
en25 English pajenegod 2024-10-18 02:40:25 4 Tiny change: 'mpared to DFS or BFS. For on' -> 'mpared to BFS or DFS. For on'
en24 English pajenegod 2024-10-18 02:32:59 6 Tiny change: 'mpared to an adjace' -> 'mpared to using an adjace'
en23 English pajenegod 2024-10-18 02:32:30 4 Tiny change: 'hbours of node.`\n\' -> 'hbours of the node.`\n\'
en22 English pajenegod 2024-10-18 02:31:12 7
en21 English pajenegod 2024-10-18 02:18:58 57
en20 English pajenegod 2024-10-18 02:14:41 4 Tiny change: 'Ring away leaf from' -> 'Ring away the leaf from'
en19 English pajenegod 2024-10-18 02:10:09 6 Tiny change: 'ittle time/memory. Fo' -> 'ittle time and memory. Fo'
en18 English pajenegod 2024-10-18 02:09:21 1 Tiny change: 'inked_list .\n\nThe X' -> 'inked_list.\n\nThe X'
en17 English pajenegod 2024-10-18 02:07:45 150
en16 English pajenegod 2024-10-18 01:42:13 10 Tiny change: ' one leaf using a w' -> ' one leaf at a time using a w'
en15 English pajenegod 2024-10-18 01:40:06 4 Tiny change: 'o call it _XOR Link' -> 'o call it the _XOR Link'
en14 English pajenegod 2024-10-18 01:37:10 25
en13 English pajenegod 2024-10-18 01:36:38 20
en12 English pajenegod 2024-10-18 01:35:21 5 Tiny change: 'lems, you need specifica' -> 'lems, you specifica'
en11 English pajenegod 2024-10-18 01:34:37 13 Tiny change: 'different than DFS or BF' -> 'different compared to DFS or BF'
en10 English pajenegod 2024-10-18 01:33:15 84
en9 English pajenegod 2024-10-18 01:31:55 13
en8 English pajenegod 2024-10-18 01:30:52 1 Tiny change: '/`.append`s calls.\n\' -> '/`.append` calls.\n\'
en7 English pajenegod 2024-10-18 01:30:17 13 Tiny change: 'o through the list of edges and' -> 'o through all of the edges and'
en6 English pajenegod 2024-10-18 01:29:29 17 Tiny change: 'st .\n\nThis is a tech' -> 'st .\n\nThe XOR Linked Tree is a tech'
en5 English pajenegod 2024-10-18 01:28:44 16
en4 English pajenegod 2024-10-18 01:26:02 1706 Tiny change: ' I saw it was being use' -> ' I saw it being use'
en3 English pajenegod 2024-10-18 00:49:58 3 Tiny change: ' algorithm. \n\n## Dis' -> ' algorithm!\n\n## Dis'
en2 English pajenegod 2024-10-18 00:46:04 1884 Tiny change: 'e are no `.push_back`/`.append`.\n\n**Cla' -> 'e are no `vector<vector>`s.\n\n**Cla'
en1 English pajenegod 2024-10-18 00:15:45 2085 Initial revision (saved to drafts)