結果

問題 No.1983 [Cherry 4th Tune C] 南の島のマーメイド
ユーザー lam6er
提出日時 2025-03-31 17:37:38
言語 PyPy3
(7.3.15)
結果
WA  
実行時間 -
コード長 5,827 bytes
コンパイル時間 235 ms
コンパイル使用メモリ 82,536 KB
実行使用メモリ 366,132 KB
最終ジャッジ日時 2025-03-31 17:39:10
合計ジャッジ時間 46,883 ms
ジャッジサーバーID
(参考情報)
judge1 / judge3
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 16 WA * 25
権限があれば一括ダウンロードができます

ソースコード

diff #

import sys
from sys import stdin
from collections import defaultdict, deque

sys.setrecursionlimit(1 << 25)

def main():
    input = sys.stdin.read
    data = input().split()
    ptr = 0
    N, M, Q = map(int, data[ptr:ptr+3])
    ptr += 3

    edges = []
    adj = [[] for _ in range(N+1)]
    for _ in range(M):
        u = int(data[ptr])
        v = int(data[ptr+1])
        ptr += 2
        adj[u].append((v, len(edges)))
        adj[v].append((u, len(edges)))
        edges.append((u, v))

    # Find all bridges using Tarjan's algorithm (iterative)
    bridges = set()
    index = 0
    indices = [0]*(N+1)
    low = [0]*(N+1)
    visited = [False]*(N+1)
    edge_stack = []

    for start in range(1, N+1):
        if not visited[start]:
            stack = [(start, -1, -1, False)]
            while stack:
                node, parent, edge_id, is_processed = stack.pop()
                if is_processed:
                    if parent != -1:
                        low[parent] = min(low[parent], low[node])
                        if low[node] > indices[parent]:
                            bridges.add(edge_id)
                else:
                    if visited[node]:
                        continue
                    visited[node] = True
                    indices[node] = index
                    low[node] = index
                    index += 1
                    stack.append((node, parent, edge_id, True))
                    for neighbor, eid in adj[node]:
                        if not visited[neighbor]:
                            stack.append((neighbor, node, eid, False))
                        elif eid != edge_id and neighbor != parent:
                            low[node] = min(low[node], indices[neighbor])

    # Assign 2-edge-connected components (BFS avoiding bridges)
    component = [0]*(N+1)
    comp_id = 0
    visited = [False]*(N+1)
    for u in range(1, N+1):
        if not visited[u]:
            comp_id += 1
            q = deque()
            q.append(u)
            visited[u] = True
            component[u] = comp_id
            while q:
                v = q.popleft()
                for neighbor, eid in adj[v]:
                    if not visited[neighbor] and eid not in bridges:
                        visited[neighbor] = True
                        component[neighbor] = comp_id
                        q.append(neighbor)

    # DSU for original graph to check connectivity
    parent = list(range(N+1))
    def find(u):
        while parent[u] != u:
            parent[u] = parent[parent[u]]
            u = parent[u]
        return u
    def union(u, v):
        u_root = find(u)
        v_root = find(v)
        if u_root != v_root:
            parent[v_root] = u_root

    for u, v in edges:
        union(u, v)

    # Build bridge tree
    bt_adj = defaultdict(list)
    comp_nodes = defaultdict(list)
    comp_size = defaultdict(int)
    for u in range(1, N+1):
        c = component[u]
        comp_nodes[c].append(u)
        comp_size[c] += 1

    for eid in bridges:
        u, v = edges[eid]
        c1 = component[u]
        c2 = component[v]
        bt_adj[c1].append(c2)
        bt_adj[c2].append(c1)

    LOG = 20
    up = [[0]*(comp_id+1) for _ in range(LOG)]
    has_large = [[False]*(comp_id+1) for _ in range(LOG)]
    depth = [0]*(comp_id+1)

    def build_binary_lifting(c_root, tree):
        q = deque()
        q.append((c_root, -1, 0))
        up[0][c_root] = -1
        depth[c_root] = 0
        while q:
            u, p, d = q.popleft()
            for v in tree[u]:
                if v != p and up[0][v] == 0:
                    up[0][v] = u
                    depth[v] = d + 1
                    q.append((v, u, d + 1))
        for u in tree.keys():
            if up[0][u] == 0:
                up[0][u] = -1
        up[0][c_root] = -1

        for k in range(1, LOG):
            for u in tree.keys():
                if up[k-1][u] == -1:
                    up[k][u] = -1
                    has_large[k][u] = has_large[k-1][u]
                else:
                    up[k][u] = up[k-1][up[k-1][u]]
                    has_large[k][u] = has_large[k-1][u] or has_large[k-1][up[k-1][u]]

    for node in bt_adj.keys():
        if up[0][node] == 0:
            build_binary_lifting(node, bt_adj)

    for c in comp_nodes:
        k = comp_size[c] > 1
        for i in range(LOG):
            has_large[i][c] = k or (has_large[i][c] if up[i][c] != -1 else False)

    def lca(u, v):
        if depth[u] < depth[v]:
            u, v = v, u
        for k in reversed(range(LOG)):
            if depth[u] - (1 << k) >= depth[v]:
                u = up[k][u]
        if u == v:
            return u
        for k in reversed(range(LOG)):
            if up[k][u] != -1 and up[k][u] != up[k][v]:
                u = up[k][u]
                v = up[k][v]
        return up[0][u]

    def has_large_on_path(u, lca_node):
        current = u
        res = False
        for k in reversed(range(LOG)):
            if depth[current] - (1 << k) >= depth[lca_node]:
                res |= has_large[k][current]
                current = up[k][current]
        return res

    output = []
    for _ in range(Q):
        x = int(data[ptr])
        y = int(data[ptr+1])
        ptr +=2
        if find(x) != find(y):
            output.append("No")
            continue
        if x == y:
            output.append("No")
            continue
        cx = component[x]
        cy = component[y]
        if cx == cy:
            output.append("No")
            continue
        l = lca(cx, cy)
        res1 = has_large_on_path(cx, l)
        res2 = has_large_on_path(cy, l)
        if res1 or res2:
            output.append("No")
        else:
            output.append("Yes")

    print('\n'.join(output))

if __name__ == "__main__":
    main()
0