相关题目:
1135. 最低成本联通所有城市
1584. 连接所有点的最小费用
261. 以图判树
class Kruskal3:
"""
K算法
最小生成树算法 MST Minimal Spanning Tree
保证整个拓扑图的所有路径之和最小
三个要点
1、包含图中的所有节点
2、形成的结构是树结构(不包括环)
3、权重和最小
其中1和2 可以结合并查集实现;3可以通过贪心算法实现,将所有边按照权重从大到小排序,如果这条边和
mst中的其他边不会形成环,则这条边事mst中的一部分,加入mst集合,如果形成环,则跳过,直到遍历完所有边为止。
"""
def minimumCost(self, n, connections: List[List[int]]):
"""
最低成本联通所有城市
https://leetcode.cn/problems/connecting-cities-with-minimum-cost/
:param n:
:param connections:
:return:
"""
# 城市编号为 1……n,初始化大小为n+1
uf = UnionFind2(n+1)
# 对边权重从小到大排序
connections = sorted(connections, key=lambda x: x[2])
# 记录最小生成树权重之和
mst = 0
for connection in connections:
src = connection[0]
dst = connection[1]
weight = connection[2]
if not uf.connected(src, dst):
mst += weight
uf.union(src, dst)
# 保证所有节点被连通,节点0没有被使用,额外占用一个连通分量
return mst if uf.count == 2 else -1
class UnionFind2:
"""
并查集算法
"""
def __init__(self, n):
self.parent = [i for i in range(n)]
self.rank = [0] * n
self.count = n
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def union(self, u, v):
root_u = self.find(u)
root_v = self.find(v)
if root_u == root_v:
return
if self.rank[u] > self.rank[v]:
self.parent[root_v] = root_u
elif self.rank[u] < self.rank[v]:
self.parent[root_u] = root_v
else:
self.parent[root_v] = root_u
self.rank[root_u] += 1
self.count -= 1
def connected(self, u, v):
root_u = self.find(u)
root_v = self.find(v)
return root_v == root_u
# 1584. 连接所有点的最小费用
class Solution:
def minCostConnectPoints(self, points: List[List[int]]) -> int:
n = len(points)
# 生成两两节点之间的边权重
edges = []
for i in range(n):
for j in range(i, n):
edges.append([i, j, abs(points[j][0] - points[i][0]) + abs(points[j][1] - points[i][1])])
edges = sorted(edges, key=lambda x: x[2])
# 执行 kruskal 算法
mst = 0
uf = UnionFind2(n)
for edge in edges:
u = edge[0]
v = edge[1]
cost = edge[2]
if not uf.connected(u, v):
mst += cost
uf.union(u, v)
return mst
class UnionFind2:
"""
并查集算法
"""
def __init__(self, n):
self.parent = [i for i in range(n)]
self.rank = [0] * n
self.count = n
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def union(self, u, v):
root_u = self.find(u)
root_v = self.find(v)
if root_u == root_v:
return
if self.rank[u] > self.rank[v]:
self.parent[root_v] = root_u
elif self.rank[u] < self.rank[v]:
self.parent[root_u] = root_v
else:
self.parent[root_v] = root_u
self.rank[root_u] += 1
self.count -= 1
def connected(self, u, v):
root_u = self.find(u)
root_v = self.find(v)
return root_v == root_u
# 261. 以图判树
def validTree(n: int, edges: List[List[int]]) -> bool:
uf = UnionFind2(n)
for edge in edges:
u = edge[0]
v = edge[1]
if uf.connected(u, v):
return False
uf.union(u, v)
# 要保证最后只形成了⼀棵树,即只有⼀个连通分量
return uf.count() == 1;