在图论中最小生成树算法中,除了常用的Prim算法之外,还有kruskal算法,该算法也是贪心的思想。
如果说Prim算法是贪心策略是选取当前距离集合最小的边,而kruskal算法的策略测试选择所有边中最小的边,这点和最短路径中的Bellman算法有异曲同工之妙。
详细的判定流程和方法也很简单:
首先要明确的是,选取的边的两个节点都是所谓的“连通量”;所谓连通量和prim算法中的集合大致意义相同,每次选择边,也会将两个点合并为一个连通量,也就是一个集合。
在初始状态下,首先每个点就是一个连通分量。
选择当前所有边中权值最小的边,并且边符合一个条件:边的两边点属于不同的两个联通分量,如果选择该边,将两个连通分量合并为一个;
重复上操作直至所有连通分量变为一个。
此时,就可以找出一个唯一的最小生成树;
对于这个算法,有两个问题需要考虑:
1.如果在不连续构造树的情况下构造生成树,也就是只关注于加边;
2.如果进行不同连通分量的判定;
在这里,我承认自己学艺不精,没有想到之前的并查集神器,也将其中的原理忘得一干二净。
如果使用并查集,就可以很好的同时解决这两个问题;
对于集合的判定合并,只需要每次在集合中查询其根节点,从而判断根节点是否为同一个,不是的话将根节点进行覆盖合并;
同时,在最后,并查集必定变成了一个根节点构成的树,此时,索引之间的关系也揭示了树的结构;
相关代码如下:
struct edge{
int u,v;
int cost;
}E[MAXV];
int kruskal(int n,int m){
int ans=0;//权值和
int Num_Edge=0;//生成的边数
for(int i=1;i<=n;i++){
father[i]=i;
//并查集初始化
}
sort(E,E+m,cmp);
for(int i=0;i