โจทย์
มี N เมือง (1..N) และ connections [city1, city2, cost] หา Minimum Spanning Tree (MST) cost เพื่อเชื่อมเมืองทั้งหมด ถ้าไม่ได้ → -1
ตัวอย่าง: N=3, connections=[[1,2,5],[1,3,6],[2,3,1]] → MST = edges (2,3) และ (1,2) cost = 1+5=6 แต่ output ในตัวอย่างคือ -1 (อาจมีข้อผิดพลาดในตัวอย่างต้นฉบับ)
อัลกอริทึม: Kruskal's Algorithm + Union-Find (DSU)
- เรียง edges ตาม cost น้อยไปมาก
- Union-Find (Disjoint Set Union) ตรวจสอบ cycle
- Greedy: เลือก edge ที่ cheap ที่สุดที่ไม่ทำ cycle
- หยุดเมื่อเลือกได้
N-1edges (connected)
การติดตั้ง (Python Implementation)
class Solution:
def minimumCost(self, n: int, connections: list[list[int]]) -> int:
# Union-Find (DSU)
parent = list(range(n + 1))
rank = [0] * (n + 1)
def find(x):
if parent[x] != x:
parent[x] = find(parent[x]) # Path compression
return parent[x]
def union(x, y):
px, py = find(x), find(y)
if px == py:
return False
# Union by rank
if rank[px] < rank[py]:
parent[px] = py
elif rank[px] > rank[py]:
parent[py] = px
else:
parent[py] = px
rank[px] += 1
return True
# Kruskal
connections.sort(key=lambda x: x[2]) # sort by cost
total_cost = 0
edges_used = 0
for u, v, cost in connections:
if union(u, v):
total_cost += cost
edges_used += 1
if edges_used == n - 1:
break
return total_cost if edges_used == n - 1 else -1
# ทดสอบ
ob = Solution()
print(ob.minimumCost(3, [[1,2,5], [1,3,6], [2,3,1]])) # 6 (ไม่ใช่ -1 ตามโจทย์ต้นฉบับ)
print(ob.minimumCost(4, [[1,2,3],[3,4,4]])) # -1 (disconnected)
Output
6 -1
แก้ไขตัวอย่างต้นฉบับ
ตัวอย่างในโจทย์เดิมให้ output -1 แต่จริงๆ แล้ว N=3 connections ครบ 3 edges สามารถเชื่อมได้ทั้งหมด MST cost = 6 (เลือก edge cost 1 และ 5) อาจเป็นข้อผิดพลาดในตัวอย่าง
Complexity
- Time: O(E log E) สำหรับ sort + O(E α(N)) สำหรับ Union-Find (α = inverse Ackermann ~ O(1))
- Space: O(N) สำหรับ parent/rank arrays
Alternative: Prim's Algorithm
เหมาะสำหรับ dense graph (E ≈ V²) ใช้ Priority Queue
import heapq
def minimumCost_prim(n, connections):
adj = [[] for _ in range(n+1)]
for u, v, w in connections:
adj[u].append((v, w))
adj[v].append((u, w))
visited = [False] * (n+1)
min_heap = [(0, 1)] # (cost, node)
total = 0
count = 0
while min_heap and count < n:
cost, u = heapq.heappop(min_heap)
if visited[u]:
continue
visited[u] = True
total += cost
count += 1
for v, w in adj[u]:
if not visited[v]:
heapq.heappush(min_heap, (w, v))
return total if count == n else -1
สรุป
Minimum Spanning Tree (MST) เป็นโจทย์คลาสสิก ใช้ Kruskal (sparse graph) หรือ Prim (dense graph) พร้อม Union-Find สำหรับ cycle detection
หากมีข้อสงสัย สามารถถามได้ในส่วนความคิดเห็นครับ