グラフィックアルゴリズム-Union Find、LCA


Union Find(サブセット)

  • これこそ判別のための資料構造です.

  • コレクションの検索や検索などの操作をサポートします.

  • 接続を検索するために使用される最上位の親.
  • と集合演算を確認し、2つの相互接続ノードA、Bを決定する.
  • A,BのルートノードA',B'が見つかりました.
  • A""を"B"の親ノードに設定...
  • すべての集約演算が処理されるまで、
  • を繰り返します.

  • 接続性によって形状を簡単に決定します.
  • def find_parent(parent, x):
        # 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
        if parent[x] != x:
            return parent[x] = find_parent(parent, parent[x])
        return parent[x]
    
    # 두 원소가 속한 집합을 합치기
    def union_parent(parent, a, b):
        a = find_parent(parent, a)
        b = find_parent(parent, b)
        if a < b:
            parent[b] = a
        else:
            parent[a] = b
    
    # 노드의 개수와 간선(Union 연산)의 개수 입력 받기
    v, e = map(int, input().split())
    parent = [0] * (v + 1) # 부모 테이블 초기화하기
    
    # 부모 테이블상에서, 부모를 자기 자신으로 초기화
    for i in range(1, v + 1):
        parent[i] = i
    
    # Union 연산을 각각 수행
    for i in range(e):
        a, b = map(int, input().split())
        union_parent(parent, a, b)
    
    # 각 원소가 속한 집합 출력하기
    print('각 원소가 속한 집합: ', end='')
    for i in range(1, v + 1):
        print(find_parent(parent, i), end=' ')
    
    print()
    
    # 부모 테이블 내용 출력하기
    print('부모 테이블: ', end='')
    for i in range(1, v + 1):
        print(parent[i], end=' ')
    
  • では、図内に周期を判別することはできない.

  • 各幹線を確認し、2つのノードのルートノードを確認します.
  • のノードが異なる場合、2つのノードを集約します.
  • が違うといえば、サイクルが発生します.

  • すべての幹線について上記の手順を繰り返します.
  • # 특정 원소가 속한 집합을 찾기
    def find_parent(parent, x):
        # 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
        if parent[x] != x:
            parent[x] = find_parent(parent, parent[x])
        return parent[x]
    
    # 두 원소가 속한 집합을 합치기
    def union_parent(parent, a, b):
        a = find_parent(parent, a)
        b = find_parent(parent, b)
        if a < b:
            parent[b] = a
        else:
            parent[a] = b
    
    # 노드의 개수와 간선(Union 연산)의 개수 입력 받기
    v, e = map(int, input().split())
    parent = [0] * (v + 1) # 부모 테이블 초기화하기
    
    # 부모 테이블상에서, 부모를 자기 자신으로 초기화
    for i in range(1, v + 1):
        parent[i] = i
    
    cycle = False # 사이클 발생 여부
    
    for i in range(e):
        a, b = map(int, input().split())
        # 사이클이 발생한 경우 종료
        if find_parent(parent, a) == find_parent(parent, b):
            cycle = True
            break
        # 사이클이 발생하지 않았다면 합집합(Union) 연산 수행
        else:
            union_parent(parent, a, b)
    
    if cycle:
        print("사이클이 발생했습니다.")
    else:
        print("사이클이 발생하지 않았습니다.")
    
    LCA
  • ノードの共通の祖先の中で最も近い祖先を見つけるために.
  • アルゴリズム#アルゴリズム#
  • のすべてのノードの深さを計算します.
  • は、最小の汎用祖先が見つかった2つのノードを確認する.
    2-1. 2つのノードの同じ深さに遡ります.
    2-2. 親ノードが同じになるまで繰り返し、2つのノードの親ノードに戻ります.
  • は、すべてのLCA(a,b)に対して第2のプロセスを繰り返す.
  • def find_depth_dfs(x,depth):
      c[x] = True
      d[x] = depth
      for i in g[x]:
        if c[i]:
          continue
        parent[i] = x
        find_depth_dfs(i,depth+1)
    
    def lca (a,b):
      # depth가 동일하도록 만듦
      while d[a] != d[b]:
        if d[a] > d[b]:
          a = parent[a]
        else:
          b = parent[b]
      # 노드가 같아지도록 만듦
      while a != b:
        a= parent[a]
        b= parent[b]
      
      return a