Source code for titan_pylib.graph.get_biconnected_components

[docs] 1def get_biconnected_components( 2 G: list[list[int]], 3) -> tuple[list[list[int]], list[list[tuple[int, int]]]]: 4 """``G`` を二重頂点連結分解します。 5 :math:`O(n+m)` です。 6 7 Args: 8 G (list[list[int]]): 隣接リストです。 9 10 Returns: 11 tuple[list[list[int]], list[list[tuple[int, int]]]]: ``(頂点集合), (辺集合)`` のタプルです。 12 """ 13 n = len(G) 14 order = [-1] * n 15 lowlink = [-1] * n 16 indx = [0] * n 17 cur_time = 0 18 stack = [] 19 edge_ans = [] 20 vertex_ans = [] 21 22 def dfs(v: int, p: int = -1) -> None: 23 nonlocal cur_time 24 dfs_stack = [(v, -1)] 25 while dfs_stack: 26 v, p = dfs_stack.pop() 27 if v >= 0: 28 if indx[v] == len(G[v]): 29 continue 30 if indx[v] == 0: 31 order[v] = cur_time 32 lowlink[v] = cur_time 33 cur_time += 1 34 while indx[v] < len(G[v]): 35 x = G[v][indx[v]] 36 indx[v] += 1 37 if x == p: 38 continue 39 if order[x] < order[v]: 40 stack.append((min(v, x), max(v, x))) 41 if order[x] == -1: 42 if indx[v] != len(G[v]): 43 dfs_stack.append((v, p)) 44 dfs_stack.append((~x, v)) 45 dfs_stack.append((x, v)) 46 break 47 else: 48 lowlink[v] = min(lowlink[v], order[x]) 49 else: 50 x, v = ~v, p 51 lowlink[v] = min(lowlink[v], lowlink[x]) 52 if lowlink[x] >= order[v]: 53 min_vx, max_vx = min(x, v), max(x, v) 54 this_edge_ans, this_vertex_ans = [], [] 55 while True: 56 a, b = stack.pop() 57 this_edge_ans.append((a, b)) 58 this_vertex_ans.append(a) 59 this_vertex_ans.append(b) 60 if min_vx == a and max_vx == b: 61 break 62 edge_ans.append(this_edge_ans) 63 vertex_ans.append(list(set(this_vertex_ans))) 64 65 for root in range(n): 66 if order[root] == -1: 67 pre_len = len(vertex_ans) 68 dfs(root) 69 if len(vertex_ans) == pre_len: 70 vertex_ans.append([root]) 71 edge_ans.append([]) 72 return vertex_ans, edge_ans