关于kruskal算法的一些个人理解
2019-01-26 21:09
141 查看
在图论中最小生成树算法中,除了常用的Prim算法之外,还有kruskal算法,该算法也是贪心的思想。
如果说Prim算法是贪心策略是选取当前距离集合最小的边,而kruskal算法的策略测试选择所有边中最小的边,这点和最短路径中的Bellman算法有异曲同工之妙。
详细的判定流程和方法也很简单:
首先要明确的是,选取的边的两个节点都是所谓的“连通量”;所谓连通量和prim算法中的集合大致意义相同,每次选择边,也会将两个点合并为一个连通量,也就是一个集合。
在初始状态下,首先每个点就是一个连通分量。
选择当前所有边中权值最小的边,并且边符合一个条件:边的两边点属于不同的两个联通分量,如果选择该边,将两个连通分量合并为一个;
重复上操作直至所有连通分量变为一个。
此时,就可以找出一个唯一的最小生成树;
对于这个算法,有两个问题需要考虑:
1.如果在不连续构造树的情况下构造生成树,也就是只关注于加边;
2.如果进行不同连通分量的判定;
在这里,我承认自己学艺不精,没有想到之前的并查集神器,也将其中的原理忘得一干二净。
如果使用并查集,就可以很好的同时解决这两个问题;
对于集合的判定合并,只需要每次在集合中查询其根节点,从而判断根节点是否为同一个,不是的话将根节点进行覆盖合并;
同时,在最后,并查集必定变成了一个根节点构成的树,此时,索引之间的关系也揭示了树的结构;
相关代码如下:
[code]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<m;i++){ int faU=findFather(E[i].u); int faV=findFather(E[i].v); if(faU!=faV){ father[faU]==faV; ans+=E[i].cost; Num_Edge++; if(Num_Edge==n-1) break; } } if(Num_Edge!=n-1) return -1; else return ans; }
相关文章推荐
- 关于开发的一些流程和个人理解
- 关于C#中 out/ref的一些个人理解
- 关于高考英语阅读理解的一些个人技巧1.17
- 关于最长路径的一些个人理解
- 关于JDBC的一些个人理解
- 关于大数据的一些个人理解
- 关于Vue中组件传值,以及emit方法的一些个人理解
- 关于拓扑排序的一些个人理解
- 关于Promise的一些个人理解jQuery的deferred
- 【原创】关于操作符重载的一些个人理解
- 关于内核中spinlock的一些个人理解 【转】
- 关于在线处理算法求最大子列和的个人一些理解
- 关于事件与委托的一些个人简单理解
- 关于线程方法的一些个人理解
- 关于bash与sh的话题(限于一般linux),以下个人的一些总结及理解,有理解错误的地方还望指点
- 关于WebRtc的一些个人理解
- 关于BFS广度优先搜索的一些个人理解
- 关于AOP的一些个人理解
- 关于jvm\hashmap和java数据结构个人的一些理解
- 关于数组的一些个人理解和源码