最小生成树的两种方法(Kruskal算法和Prim算法)

本文介绍了图论的基本概念,包括连通图、强连通图等,并详细阐述了最小生成树的概念及求解算法——Kruskal算法与Prim算法的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于图的几个概念定义:

  • 连通图:在无向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该无向图为连通图。
  • 强连通图:在有向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该有向图为强连通图。
  • 连通网:在连通图中,若图的边具有一定的意义,每一条边都对应着一个数,称为权;权代表着连接连个顶点的代价,称这种连通图叫做连通网。
  • 生成树:一个连通图的生成树是指一个连通子图,它含有图中全部n个顶点,但只有足以构成一棵树的n-1条边。一颗有n个顶点的生成树有且仅有n-1条边,如果生成树中再添加一条边,则必定成环。
  • 最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树。 
    这里写图片描述

下面介绍两种求最小生成树算法

对于最小生成树问题,有两种解决方法,*Prim*与*Kruskacl*,复杂度分别为O(m*logn) O(m*logm),一下是对其两种算法的简单介绍

 

Kruskal算法

Kruskal(克鲁斯卡尔)算法是一种巧妙利用并查集来求最小生成树的算法。

  首先我们把无向图中相互连通的一些点称为处于同一个连通块中。例如下图

图中有3个连通块。1、2处于一个连通块中,4、5、6也处于一个连通块中,孤立点3也称为一个连通块。

Kruskal算法将一个连通块当做一个集合。Kruskal首先将所有的边按从小到大顺序排序(一般使用快排),并认为每一个点都是孤立的,分属于n个独立的集合。然后按顺序枚举每一条边。如果这条边连接着两个不同的集合,那么就把这条边加入最小生成树,这两个不同的集合就合并成了一个集合;如果这条边连接的两个点属于同一集合,就跳过。直到选取了n-1条边为止。

 

算法描述:

 

  1. 初始化并查集。father[x]=x,
  2. tot=0
  3. 将所有边用快排从小到大排序。
  4. 计数器 k=0;
  5. for (i=1; i<=M; i++)      //循环所有已从小到大排序的边

 

if 这是一条u,v不属于同一集合的边(u,v)(因为已经排序,所以必为最小),

 

     ①合并u,v所在的集合,相当于把边(u,v)加入最小生成树。

 

     ②tot=tot+W(u,v)

 

      ③k++

 

      ④如果k=n-1,说明最小生成树已经生成,则break;

 

  1. 结束,tot即为最小生成树的总权值之和。

 

1.Kruskal算法

此算法可以称为“加边法”,初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里。 
1. 把图中的所有边按代价从小到大排序; 
2. 把图中的n个顶点看成独立的n棵树组成的森林; 
3. 按权值从小到大选择边,所选的边连接的两个顶点ui,viui,vi,应属于两颗不同的树,则成为最小生成树的一条边,并将这两颗树合并作为一颗树。 
4. 重复(3),直到所有顶点都在一颗树内或者有n-1条边为止。

这里写图片描述

2.Prim算法

此算法可以称为“加点法”,每次迭代选择代价最小的边对应的点,加入到最小生成树中。算法从某一个顶点s开始,逐渐长大覆盖整个连通网的所有顶点。

  1. 图的所有顶点集合为VV;初始令集合u={s},v=V−uu={s},v=V−u;
  2. 在两个集合u,vu,v能够组成的边中,选择一条代价最小的边(u0,v0)(u0,v0),加入到最小生成树中,并把v0v0并入到集合u中。
  3. 重复上述步骤,直到最小生成树有n-1条边或者n个顶点为止。

由于不断向集合u中加点,所以最小代价边必须同步更新;需要建立一个辅助数组closedge,用来维护集合v中每个顶点与集合u中最小代价边信息,:

 

 

Prim算法

Prim算法采用与Dijkstra、Bellman-Ford算法一样的“蓝白点”思想:白点代表已经进入最小生成树的点,蓝点代表未进入最小生成树的点。

算法描述:

以1为起点生成最小生成树,min[v]表示蓝点v与白点相连的最小边权。MST表示最小生成树的权值之和。

一:初始化:min[v]= ∞(v≠1); min[1]=0;MST=0;

二:for (i = 1; i<= n; i++)

1.寻找min[u]最小的蓝点u。

2.将u标记为白点

3.MST+=min[u]

4.for 与白点u相连的所有蓝点v  

  if (w[u][v]<min[v])

 min[v]=w[u][v];

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值