最小生成树

复健中

最小生成树是基本的图论算法。

P3366 【模板】最小生成树

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz

输入格式

第一行包含两个整数 ,表示该图共有 个结点和 条无向边。

接下来 行每行包含三个整数 ,表示有一条长度为 的无向边连接结点

输出格式

如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出 orz

输入输出样例 #1

输入 #1

1
2
3
4
5
6
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3

输出 #1

1
7

说明/提示

数据规模:

对于 的数据,

对于 的数据,

对于 的数据,

对于 的数据:

样例解释:

所以最小生成树的总边权为

Prime 算法

核心在于,将已遍历的点连接的边拉近优先队列,然后取下一边再拉一个点进来。时间复杂度 (应该是)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import heapq
from collections import deque
n, m = map(int, input().split())
arr = [deque() for _ in range(n+1)] # 每个点的边权和下一点.其实可以不用deque
queue = []

for i in range(m):
u, v, w = map(int, input().split())
arr[u].append((w, v)) # 1到n
arr[v].append((w, u))

last = n-1
u=1
vis = [False]*(n+1)
vis[1]=True

ans=0
for p in arr[u]:
heapq.heappush(queue,p)
while queue:
while vis[u] and queue:
w,u=heapq.heappop(queue)
if vis[u]:
break
ans+=w
vis[u]=True
last-=1
if not last:
break
while arr[u]:
w,v=arr[u].pop()
if not vis[v]:
heapq.heappush(queue,(w,v))

if not last:
print(ans)
else:
print('orz')

Kruskal 算法

核心在于把所有边带着两个端点放进优先队列,每次取一条全局最短边,连接两个点所在的树。时间复杂度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import heapq
n, m = map(int, input().split())
arr = []
last = n-1
for i in range(m):
u, v, w = map(int, input().split())
arr.append((w, u, v))


class Dsu:
def __init__(self, n):
self.n = n
self.parent = [i for i in range(0, n+1)]
self.size = [1]*(n+1)

def find(self, a):
if a != self.parent[a]:
self.parent[a] = self.find(self.parent[a])
return self.parent[a]

def union(self, a, b):
pa = self.find(a)
pb = self.find(b)
if pa == pb:
return
if self.size[a] < self.size[b]:
a, b = b, a
self.parent[pb] = pa
self.size[pa] += self.size[pb]

dsu = Dsu(n)
heapq.heapify(arr)
ans = 0

while arr:
w, u, v = heapq.heappop(arr)
if dsu.find(u) == dsu.find(v):
continue
ans += w
dsu.union(u,v)
last-=1
if last==0:
break
if not last:
print('orz')
else:
print(ans)