From 09a38929d200e46927cd105da0e640945a290224 Mon Sep 17 00:00:00 2001 From: yoshikazu Date: Mon, 27 Jul 2026 15:38:03 +0000 Subject: [PATCH] Add UnionFind --- Sources/Photochk/Core/UnionFind.swift | 50 +++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Sources/Photochk/Core/UnionFind.swift diff --git a/Sources/Photochk/Core/UnionFind.swift b/Sources/Photochk/Core/UnionFind.swift new file mode 100644 index 0000000..b7b9812 --- /dev/null +++ b/Sources/Photochk/Core/UnionFind.swift @@ -0,0 +1,50 @@ +import Foundation + +/// 経路圧縮 + ランク併合の Union-Find。類似ペアから連結成分(グループ)を作るのに使う。 +struct UnionFind { + private var parent: [Int] + private var rank: [Int] + + init(count: Int) { + parent = Array(0.. Int { + var root = x + while parent[root] != root { root = parent[root] } + // 経路圧縮 + var node = x + while parent[node] != root { + let next = parent[node] + parent[node] = root + node = next + } + return root + } + + @discardableResult + mutating func union(_ a: Int, _ b: Int) -> Bool { + let ra = find(a) + let rb = find(b) + guard ra != rb else { return false } + if rank[ra] < rank[rb] { + parent[ra] = rb + } else if rank[ra] > rank[rb] { + parent[rb] = ra + } else { + parent[rb] = ra + rank[ra] += 1 + } + return true + } + + /// 連結成分を、根のインデックスをキーにしてまとめて返す。 + mutating func components() -> [[Int]] { + var buckets: [Int: [Int]] = [:] + for i in parent.indices { + buckets[find(i), default: []].append(i) + } + return Array(buckets.values) + } +}