听骚话讲作者

[手动滑稽]
其实早就该写这篇博客啦。

图的最小生成树

一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。最小生成树可以用kruskal(克鲁斯卡尔)算法或Prim(普里姆)算法求出。
换句话说,就是使原图变成一棵树并且要求这棵树中保留的边最小。(变树的过程需要删除边)
如下图,红线为此图的一个最小生成树:

浅谈克鲁斯卡尔算法

克鲁斯卡尔算法是一种用来寻找最小生成树的算法。在剩下的所有未选取的边中,找最小边,如果和已选取的边构成回路,则放弃,选取次小边。
根据克鲁斯卡尔算法定义,我们要解决以下问题:

1.选择多少条这样的边?
2.使用什么思想来解决?(贪心,动态规划,数论,分治,递归,递推。。。。。。)

对于第一个问题,我们很容易可以得到答案。假设有n个点,那么必然保留n-1条边,只有这样才满足树的性质。

满足了树的性质,我们还要满足“最小”的性质。
在克鲁斯卡尔算法中,我们选择使用贪心法来解决。

我们为了取用最小的边,所以对所有的边进行排序,并从最小的开始选取。
为此,我们需要一个存储边以及边权的表,如下图:

struct e{int u,v,order,s;e(){u=v=order=0;return;}bool operator < (const e &x)const{if(s<x.s) return 1;return 0;}
}edge[maxm];

这里使用了运算符重载,因为我们要的只是对边权排序,而其他所有和边有关的变量一起被排序。
对这种捆绑排序和运算符重载不理解的可以戳这里:戳我手动滑稽一下
使用下面这个函数有助于你往边表里添加边,当然你可以不写这个函数。

void addedge(int u,int v,int s,int order){  //这不是邻接表! edge[++js].u=u;edge[js].v=v;edge[js].s=s;edge[js].order=order;return;
}

这看起来很像邻接表,但是这绝对不是邻接表。这里没有链表的象征——后继指针next
如果你对我上述的话有质疑,那你一定要看这篇——邻接表存图法
这绝对不会浪费你人生的十分钟

接下来我们优美的排个序:

sort(edge+1,edge+s+1);


然而,当我们从最小的开始选取时,选完最小的两边——(1,2)和(1,3)时,有可能就会选到上图中标蓝色的边。而一旦选取了这个边,就会构成回路,这样就不满足树的性质了。
为了防止其形成回路,我们需要使用一个数据结构——并查集

不懂并查集的朋友点我

每当我们加入一条边时,便把这个边的两个端点加入并查集。然后后续选择边的时候,需要把即将添加的边的两个端点进行查找,如果不在同一个并查集里头,就可以加入该边,否则就跳过这条边而选择下一条次小的。
流程这样描述:

for(int i=1;i<=s;i++){if(time==p-1) break;if(get(edge[i].u)!=get(edge[i].v)){merge(edge[i].u,edge[i].v);cout<<edge[i].u<<" link with "<<edge[i].v<<endl;time++;}}

其中if(time==p-1) break; 就是当已经选择了p-1条边时(假设p为总点数)自动退出循环。
if(get(edge[i].u)!=get(edge[i].v)) 这个就是判断是否形成环路的,通过这层判断就代表不在同一个并查集里。
我们这里用cout<<edge[i].u<<" link with "<<edge[i].v<<endl; 来输出我们被选中的边。time是用于统计被选中的边数。
这样,克鲁斯卡尔基本上就搞定了

代码示例

样例输入 样例输出
6 10 1 link with 2
1 2 1 1 link with 3
1 3 1 2 link with 5
2 3 2 4 link with 5
2 4 3 4 link with 6
2 5 2
3 5 2
3 4 3
4 5 2
4 6 3
5 6 3
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxm=10001;
int p,s;
int a,b,c;
struct e{int u,v,order,s;e(){u=v=order=0;return;}bool operator < (const e &x)const{if(s<x.s) return 1;return 0;}
}edge[maxm];int js;
void addedge(int u,int v,int s,int order){  //这不是邻接表! edge[++js].u=u;edge[js].v=v;edge[js].s=s;edge[js].order=order;return;
} int fa[maxm];
int get(int x){if(fa[x]==x) return x;return fa[x]=get(fa[x]);
}void merge(int x,int y){x=get(x);y=get(y);if(x!=y) fa[y]=x;return;
} int time;
void kruskal(){sort(edge+1,edge+s+1);for(int i=1;i<=s;i++){if(time==p-1) break;if(get(edge[i].u)!=get(edge[i].v)){merge(edge[i].u,edge[i].v);cout<<edge[i].u<<" link with "<<edge[i].v<<endl;time++;}} return;
}int main(){std::ios::sync_with_stdio(false);cin>>p>>s;for(int i=1;i<=s;i++){cin>>a>>b>>c;addedge(a,b,c,i);}for(int i=1;i<=p;i++)fa[i]=i;kruskal();return 0;
}

克鲁斯卡尔算法(Kruskal Algorithm)——图的最小生成树相关推荐

  1. 贪心算法(Greedy Algorithm)最小生成树 克鲁斯卡尔算法(Kruskal#39;s algorithm)

    克鲁斯卡尔算法(Kruskal's algorithm)它既是古典最低的一个简单的了解生成树算法. 这充分反映了这一点贪心算法的精髓.该方法可以通常的图被表示.图选择这里借用Wikipedia在.非常 ...

  2. 无向图的最小生成树(克鲁斯卡尔算法 Kruskal)

    引子: 克鲁斯卡尔算法的作用是:构建图的最小生成树. 克鲁斯卡尔算法 Kruskal的构造过程: 1.初始化图:n个顶点,n个连通分量(如果两个顶点的连通分量相同,表示两点在同一个连通图中).把所有的 ...

  3. Java普利姆算法(Prim)与克鲁斯卡尔算法(Kruskal)

    1.Java普利姆算法(Prim)与克鲁斯卡尔算法(Kruskal) 普利姆算法(Prim)与克鲁斯卡尔算法(Kruskal)求**最小生成树(极小连通子图)**的算法 1.1普利姆算法(Prim) ...

  4. 数据结构——最小生成树之克鲁斯卡尔算法(Kruskal)

    最小生成树算法 prime算法和克鲁斯卡尔算法 克鲁斯卡尔算法 思路 优先队列+并查集 Kuskal算法 [算法简介]:上一篇中的Prime算法是一种"加点式的算法",而Kuska ...

  5. prim算法求最小生成树_克鲁斯卡尔算法(Kruskal算法)求最小生成树

    上一节介绍了求最小生成树之普里姆算法.该算法从顶点的角度为出发点,时间复杂度为O(n2),更适合与解决边的绸密度更高的连通网.本节所介绍的克鲁斯卡尔算法,从边的角度求网的最小生成树,时间复杂度为O(e ...

  6. 数据结构与算法-克鲁斯卡尔算法(Kruskal) | 尚硅谷韩顺平

    提出问题 基本介绍 克鲁斯卡尔(Kruskal)算法,求加权连通图最小生成树的算法 基本思想:按权值从小到大顺序选择n-1条边,保证n-1条边不够成回路 具体做法:先构造一个只有n顶点的森林,然后按权 ...

  7. 最小生成树练习1(克鲁斯卡尔算法Kruskal)

    今天刷一下水题练手入门,明天继续. poj1861 Network(最小生成树)新手入门题. 题意:输出连接方案中最长的单根网线长度(必须使这个值是所有方案中最小的),然后输出方案. 题解:本题没有直 ...

  8. kruskal算法java_克鲁斯卡尔算法(Kruskal)的java实现

    下面是我对软件工程教程里面的克鲁斯卡尔算法的实现,发现在网是很少有网友贴出,为了方便大家查询,所以贴出来了,还希望大家能多指点. package Test; import java.io.Buffer ...

  9. 克鲁斯卡尔算法(Kruskal)求最小生成树(MST)过程详解

    基本思想 先构造一个只含 n 个顶点.而边集为空的子图,把子图中各个顶点看成各棵树上的根结点,之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树(不构成回路),则将其加入子图 ...

  10. 最小生成树(普利姆算法、克鲁斯卡尔算法)

    给定一个带权的无向连通图,如何选取一棵生成树,使树上所有边上权的总和为最小,这叫最小生成树. 求最小生成树的算法 (1) 克鲁斯卡尔算法 图的存贮结构采用边集数组,且权值相等的边在数组中排列次序可以是 ...

最新文章

  1. 102TimeStatistic
  2. Caffe实战二(手写体识别例程:CPU、GPU、cuDNN速度对比)
  3. PAT甲级1090 Highest Price in Supply Chain:[C++题解]树、结点到根结点的距离、记忆化搜索、树形dp
  4. Web前端培训分享:Web前端到底是什么?
  5. 元件原理图旋转45度_大口径大曲率半径光学元件的高精度检测
  6. scrt如何切换成英文版_英文版SecureCRT显示乱码解决
  7. 程序员让开,硅谷将是物理学家的天下,薪水高得离谱
  8. IPhone IPad 利用cocos2d开发游戏问题
  9. linux 查看nginx,php-fpm运行用户及用户组
  10. 用友NC系统安装部署指南
  11. windows和linux环境下java调用C++代码-JNI技术
  12. maxscale的causal_reads参数
  13. Excel表VLOOKUP多个条件匹配数据
  14. 图片服务器的架构演进
  15. Win10下AutoCAD2014 +VS2010 + Object2014 安装与配置环境
  16. 为什么别人的移动开发效率是你的2倍?丨课程推广
  17. 最简单的音频剪切和合并
  18. 一文详解计算机网络经典面试题
  19. 荒野求生获得服务器信息,荒野求生游戏问答老贝出海时任务编码 | 手游网游页游攻略大全...
  20. Java 数据结构与算法

热门文章

  1. 硬盘内部硬件结构和工作原理详解
  2. A - 娜娜梦游仙境系列——诡异的钢琴
  3. 紫外可见分光光度计 | 探索光的工具 | 详解
  4. 厦门理工嵌入式开发LPC1768开发板教程
  5. golang常用库之-mgo.v2包、MongoDB官方go-mongo-driver包、七牛Qmgo包 | go操作mongodb、mongodb bson
  6. acwing 206 石头游戏 矩阵快速幂
  7. Solr参数mm详解
  8. 17 张程序员专属壁纸(使用频率很高)
  9. 仿京东 分类 购物车 + 定位
  10. SIM卡在手机中的主要作用