From d8f62901299142dddbd3da5c2d247730e90cddb2 Mon Sep 17 00:00:00 2001 From: weilycoder Date: Thu, 3 Oct 2024 11:50:59 +0800 Subject: [PATCH 1/3] add spanning tree --- cyaron/graph.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/cyaron/graph.py b/cyaron/graph.py index ce7aea4..b772d68 100644 --- a/cyaron/graph.py +++ b/cyaron/graph.py @@ -110,6 +110,33 @@ def add_edge(self, x, y, **kwargs): if not self.directed and x != y: self.__add_edge(y, x, weight) + def to_tree(self, root = 1, *, container = list): + """to_tree(self, root, *, container) -> list[tuple[int, int]] + Return a spanning tree of the graph. + By default, return the DFS spanning tree generated from node 1 as the root. + int root = 1 -> starting from `root` to generate. + container = list -> use list to simulate a stack by default. + You can pass in a container class that implements `pop` and `append` methods. + Additionally, it needs the method `__bool__` to indicate whether the container is non-empty. + For example, pass in a heap to implement a minimum spanning tree. + """ + tree = [] + vis = set() + q = container() + q.append((0, root, 0)) + while q: + _, u, fa = q.pop() + if u in vis: + continue + vis.add(u) + tree.append((fa, u)) + for edge in self.edges[u]: + v, w = edge.end, edge.weight + if v in vis: + continue + q.append((w, v, u)) + return tree + @staticmethod def chain(point_count, **kwargs): """chain(point_count, **kwargs) -> Graph From bfafc1bfba732ea82978e9cafa2c211f53200ce2 Mon Sep 17 00:00:00 2001 From: weilycoder Date: Thu, 10 Oct 2024 15:31:43 +0800 Subject: [PATCH 2/3] Add from_weight function to print weight of edge --- cyaron/graph.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cyaron/graph.py b/cyaron/graph.py index 7079514..59e8a04 100644 --- a/cyaron/graph.py +++ b/cyaron/graph.py @@ -129,7 +129,7 @@ def add_edge(self, x, y, **kwargs): if not self.directed and x != y: self.__add_edge(y, x, weight) - def to_tree(self, root = 1, *, container = list): + def to_tree(self, root = 1, *, container = list, from_weight = lambda w: None): """to_tree(self, root, *, container) -> list[tuple[int, int]] Return a spanning tree of the graph. By default, return the DFS spanning tree generated from node 1 as the root. @@ -138,6 +138,7 @@ def to_tree(self, root = 1, *, container = list): You can pass in a container class that implements `pop` and `append` methods. Additionally, it needs the method `__bool__` to indicate whether the container is non-empty. For example, pass in a heap to implement a minimum spanning tree. + from_weight = lambda w: None -> use to print the weight of edge, if it returns `None`, the function will ignore the weight. """ tree = [] vis = set() @@ -148,7 +149,8 @@ def to_tree(self, root = 1, *, container = list): if u in vis: continue vis.add(u) - tree.append((fa, u)) + w = from_weight(_) + tree.append((fa, u) if w is None else (fa, u, w)) for edge in self.edges[u]: v, w = edge.end, edge.weight if v in vis: From 2a7b7fc6e9af4c77bcb1da243ebcc6dcd19955ed Mon Sep 17 00:00:00 2001 From: weilycoder Date: Thu, 10 Oct 2024 16:13:54 +0800 Subject: [PATCH 3/3] Cancel the form parent node of the root node --- cyaron/graph.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cyaron/graph.py b/cyaron/graph.py index 59e8a04..3b02c99 100644 --- a/cyaron/graph.py +++ b/cyaron/graph.py @@ -149,8 +149,9 @@ def to_tree(self, root = 1, *, container = list, from_weight = lambda w: None): if u in vis: continue vis.add(u) - w = from_weight(_) - tree.append((fa, u) if w is None else (fa, u, w)) + if fa != 0: + w = from_weight(_) + tree.append((fa, u) if w is None else (fa, u, w)) for edge in self.edges[u]: v, w = edge.end, edge.weight if v in vis: