目录
一、前言
再做做与图、树相关的题目,显然,用并查集能很完美地找出最小生成树,废话不多说,直接看题目。
二、最小生成树
1、上链接
2、基本思路
从权值最小的边开始依次“并”相应节点。
3、python代码(AC)
N,M=map(int,input().split())
edges=[]
for i in range(M):
x,y,z=map(int,input().split())
edges.append((x,y,z))
edges.sort(key=lambda x:x[2],reverse=True)
##for i in range(M):
## print(edges[i])
p=[i for i in range(N+1)]
def union(x,y):
p[Find(x)]=Find(y)
def Find(x):
if p[x]==x:
return x
p[x]=Find(p[x])
return p[x]
res=0
cnt=1
while edges:
e=edges.pop()
if Find(e[0])!=Find(e[1]):
union(e[0],e[1])
cnt+=1
res+=e[2]
if cnt==N:
print(res)
else:
print("orz")
这代码挺简单的,直接看便可看懂。该题我主要复习了列表的 sort 排序(其实可以在 IDLE 上测试观察的),还有 python 的匿名函数 lambda 的使用。
以上,最小生成树例题
祝好
-------------------------------------------------------------------------------
由于上文太短,发文助手机器人建议再加多点内容,好吧~
-------------------------------------------------------------------------------
1、生成树
在图论中,如果连通图的一个子图是一棵包含的所有顶点的树,则该子图称为G的生成树 (SpanningTree)。
生成树是连通图的包含图中的所有顶点的极小连通子图。
图的生成树不唯一。从不同的顶点出发进行遍历,可以得到不同的生成树。
通俗的来说,生成树就是:
- 只要能连通所有顶点而又不产生回路的任何子图都是它的生成树
- 连接图中所有的点n,并且只有n-1条边的子图就是它的生成树
2、最小生成树
自行体会。
3、kruskal算法
Kruskal 算法是能够在 O(mlogm) 的时间内得到一个最小生成树的算法。它主要是基于贪心的思想:
① 将边按照边权从小到大排序,并建立一个没有边的图 T。
② 选出一条没有被选过的边权最小的边。
③ 如果这条边两个顶点在 T 中所在的连通块不相同,那么将它加入图 T, 相同就跳过。
④ 重复②和③直到图 T 连通为止。
由于只需要维护连通性,可以不需要真正建立图 T,可以用并查集来维护。
4、prim算法
Prim 算法和 Kruskal 算法一样也是寻找最小生成树的一种方法:
① 先建立一个只有一个结点的树,这个结点可以是原图中任意的一个结点。
② 使用一条边扩展这个树,要求这条边一个顶点在树中另一 个顶点不在树中,并且这条边的权值要求最小。
③ 重复步骤②直到所有顶点都在树中。
这里记顶点数v,边数e
邻接矩阵: O(v^2)
邻接表: O(elog2v)
此为原始的加权连通图。每条边一侧的数字代表其权值。
....(举例省略)
(是不是有点像最短路算法中的迪杰斯特拉?其实代码实现也差不多)