beam: harden dsu_rollback with range validation and no-compression find

This commit is contained in:
beam committed 2026-10-27 09:15:51 +00:00
1 parent 04cdcccad2
commit e33aa301ad
1 file changed
+12
+12
View File
@@ -26,7 +26,14 @@ class DSU:
# history: list of (child_root, parent_root, old_size_parent) for undo # history: list of (child_root, parent_root, old_size_parent) for undo
self.history: List[Tuple[int, int, int]] = [] self.history: List[Tuple[int, int, int]] = []
def _check_index(self, x: int) -> None:
if not isinstance(x, int) or isinstance(x, bool):
raise TypeError("index must be int")
if x < 0 or x >= len(self.parent):
raise ValueError("index out of range")
def find(self, x: int) -> int: def find(self, x: int) -> int:
self._check_index(x)
# no path compression (required for rollback) # no path compression (required for rollback)
root = x root = x
while self.parent[root] != root: while self.parent[root] != root:
@@ -34,6 +41,8 @@ class DSU:
return root return root
def union(self, a: int, b: int) -> bool: def union(self, a: int, b: int) -> bool:
self._check_index(a)
self._check_index(b)
ra = self.find(a) ra = self.find(a)
rb = self.find(b) rb = self.find(b)
if ra == rb: if ra == rb:
@@ -60,9 +69,12 @@ class DSU:
self.sz[parent] = old_size self.sz[parent] = old_size
def size(self, x: int) -> int: def size(self, x: int) -> int:
self._check_index(x)
return self.sz[self.find(x)] return self.sz[self.find(x)]
def connected(self, a: int, b: int) -> bool: def connected(self, a: int, b: int) -> bool:
self._check_index(a)
self._check_index(b)
return self.find(a) == self.find(b) return self.find(a) == self.find(b)
def components(self) -> int: def components(self) -> int: