結果
問題 | No.1326 ふたりのDominator |
ユーザー |
![]() |
提出日時 | 2025-03-26 15:47:26 |
言語 | PyPy3 (7.3.15) |
結果 |
TLE
|
実行時間 | - |
コード長 | 6,758 bytes |
コンパイル時間 | 166 ms |
コンパイル使用メモリ | 82,252 KB |
実行使用メモリ | 186,652 KB |
最終ジャッジ日時 | 2025-03-26 15:48:35 |
合計ジャッジ時間 | 14,433 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 1 |
other | AC * 19 TLE * 1 -- * 4 |
ソースコード
import sysfrom sys import stdinfrom collections import defaultdict, dequesys.setrecursionlimit(1 << 25)def main():input = sys.stdin.read().split()ptr = 0N, M = int(input[ptr]), int(input[ptr+1])ptr +=2edges = []for _ in range(M):u = int(input[ptr])-1v = int(input[ptr+1])-1edges.append((u, v))ptr +=2Q = int(input[ptr])ptr +=1queries = []for _ in range(Q):x = int(input[ptr])-1y = int(input[ptr+1])-1queries.append((x, y))ptr +=2graph = [[] for _ in range(N)]for u, v in edges:graph[u].append(v)graph[v].append(u)# Find articulation points and biconnected componentsorder = [0]*Nlow = [0]*Nused = [0]*Narticulations = [0]*Nparent = [-1]*Nbc_edges = []stack = []bc_id = 0bc_vert_to_bc = defaultdict(list)bc_components = []current_edge = 0time = 0def dfs(u):nonlocal time, current_edgeused[u] = 1order[u] = low[u] = timetime +=1children = 0for v in graph[u]:if v == parent[u]:continueif not used[v]:stack.append((u, v))parent[v] = uchildren +=1dfs(v)low[u] = min(low[u], low[v])if (parent[u] == -1 and children >=2) or (parent[u] != -1 and low[v] >= order[u]):articulations[u] = 1if low[v] >= order[u]:component = []while True:e = stack.pop()component.append(e)if e == (u, v):breakbc_components.append(component)current_edge +=1elif order[v] < order[u]:low[u] = min(low[u], order[v])stack.append((u, v))for u in range(N):if not used[u]:dfs(u)bc_vert = [[] for _ in range(len(bc_components))]bc_edges = [[] for _ in range(len(bc_components))]for i, component in enumerate(bc_components):verts = set()for u, v in component:verts.add(u)verts.add(v)for v in verts:bc_vert_to_bc[v].append(i)bc_vert[i] = list(verts)bc_edges[i] = componentblock_to_artics = defaultdict(set)artics_to_blocks = defaultdict(set)for i in range(len(bc_components)):comp = bc_vert[i]artics = set()for v in comp:if articulations[v]:artics.add(v)for a in artics:block_to_artics[i].add(a)artics_to_blocks[a].add(i)block_tree = defaultdict(list)node_count = 0block_node = {}art_node = {}for a in artics_to_blocks:art_node[a] = node_countnode_count +=1for b in range(len(bc_components)):block_node[b] = node_countnode_count +=1for a, blocks in artics_to_blocks.items():a_node = art_node[a]for b in blocks:b_node = block_node[b]block_tree[a_node].append(b_node)block_tree[b_node].append(a_node)for b in range(len(bc_components)):b_node = block_node[b]arts = block_to_artics[b]for a in arts:a_node = art_node[a]if a_node not in block_tree[b_node]:block_tree[b_node].append(a_node)block_tree[a_node].append(b_node)B = node_countLOG = 20parent_table = [[-1]*B for _ in range(LOG)]depth = [0]*Bis_artic_node = [False]*Bfor a in art_node.values():is_artic_node[a] = Truefor b in block_node.values():is_artic_node[b] = Falsevisited = [False]*Bfor root in range(B):if not visited[root]:q = deque()q.append(root)visited[root] = Trueparent_table[0][root] = -1depth[root] = 0while q:u = q.popleft()for v in block_tree[u]:if not visited[v]:visited[v] = Trueparent_table[0][v] = udepth[v] = depth[u] +1q.append(v)for k in range(1, LOG):for v in range(B):if parent_table[k-1][v] != -1:parent_table[k][v] = parent_table[k-1][parent_table[k-1][v]]else:parent_table[k][v] = -1def lca(u, v):if depth[u] < depth[v]:u, v = v, ufor k in range(LOG-1, -1, -1):if depth[u] - (1 << k) >= depth[v]:u = parent_table[k][u]if u == v:return ufor k in range(LOG-1, -1, -1):if parent_table[k][u] != parent_table[k][v]:u = parent_table[k][u]v = parent_table[k][v]return parent_table[0][u]def get_path_arts(u, l, exclude_x, x_node, exclude_y, y_node):res = 0while u != l:if is_artic_node[u]:if exclude_x and u == x_node:passelif exclude_y and u == y_node:passelse:res +=1u = parent_table[0][u]return resfor q in range(Q):x, y = queries[q]if x == y:print(0)continuex_blocks = bc_vert_to_bc.get(x, [])y_blocks = bc_vert_to_bc.get(y, [])common = Falsex_set = set(x_blocks)for bl in y_blocks:if bl in x_set:common = Truebreakif common:print(0)continueif len(x_blocks) ==0 or len(y_blocks) ==0:print(0)continueif articulations[x]:x_node = art_node[x]else:x_block = x_blocks[0]x_node = block_node[x_block]if articulations[y]:y_node = art_node[y]else:y_block = y_blocks[0]y_node = block_node[y_block]l = lca(x_node, y_node)cnt = 0u = x_nodecnt += get_path_arts(u, l, True, x_node, False, -1)v = y_nodecnt += get_path_arts(v, l, False, -1, True, y_node)if is_artic_node[l]:if l == x_node:passelif l == y_node:passelse:cnt +=1print(cnt)if __name__ == "__main__":main()