最小生成树
首先, 什么是最小生成树
图论基础
Prim算法(普利姆算法)
采用prim算法解决生成树问题
- 假设G=(V,E)是一个具有n个顶点的连通网,T=(U,TE)是G的最小生成树,U,TE初值均为空集。
- 首先从V中任取一个顶点(假定取v1),将它并入U中,此时U={v1},然后只要U是V的真子集(U∈V),就从那些一个端点已在T中,另一个端点仍在T外的所有边中,找一条最短边,设为(vi ,vj ),其中vi ∈U, vj ∈V-U,并把该边(vi , vj )和顶点vj 分别并入T的边集TE和顶点集U,如此进行下去,每次往生成树里并入一个顶点和一条边,直到n-1次后得到最小生成树。
关键问题
每次如何从连接T 中和T 外顶点的所有边中,找到一条最短的
- 如果用邻接矩阵存放图,而且选取最短边的时候遍历所有点进行选取,则总时间复杂度为O(V 2 ), V 为顶点个数
- 用邻接表存放图,并使用堆来选取最短边,则总时间复杂度为O(ElogV)
特点 : 不加堆的Prim 算法适用于密集图,加堆的适用于稀疏图
Krustral算法(克鲁斯卡尔算法)
- 假设G=(V,E)是一个具有n个顶点的连通网,T=(U,TE)是G的最小生成树,U=V, TE初值为空。
- 将图G中的边按权值从小到大依次选取,若选取的边使生成树不形成回路,则把它并入TE中,若形成回路则将其舍弃,直到TE中包含N-1条边为止,此时T为最小生成树。
特点: 适用于稀疏图
关键问题
- 如何判断欲加入的一条边是否与生成树中边构成回路。
- 将各顶点划分为所属集合的方法来解决,每个集合的表示一个无回路的子集。开始时边集为空,N个顶点分属N个集合,每个集合只有一个顶点,表示顶点之间互不连通。
- 当从边集中按顺序选取一条边时,若它的两个端点分属于不同的集合,则表明此边连通了两个不同的部分,因每个部分连通无回路,故连通后仍不会产生回路,此边保留,同时把相应两个集合合并
经典最小生成树题目畅通工程
prim算法和kruskal算法比较
- Kruskal:
- 将所有边从小到大加入,在此过程中判断是否构成回路
- 使用数据结构:并查集
- 时间复杂度:O(ElogE)
- 适用于稀疏图
- Prim:
- 从任一节点出发,不断扩展
- 使用数据结构:堆
- 时间复杂度:O(ElogV) 或 O(VlogV+E)(斐波那契堆)
- 适用于密集图
- 若不用堆则时间复杂度为O(V2 )
最小生成树扩展
最小度数限制生成树