前言:
写了2100字,真的很不好写,各位点个赞吧
图论是个极其恶心的东西(除了最小生成树)
——————饮水思源的美西螈
算法介绍:
在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集且为无循环图,使得联通所有结点的的 w(T) 最小,则此 T 为 G 的最小生成树。
最小生成树其实是最小权重生成树的简称。
——————来自《百度百科》
这样一看肯定看不懂(除了一些神犇)
最小生成树,就是求出让整个图联通最少的权值
这么一听,和最短路径有什么区别?
最短路径,意思就是从一个点到另一个点的最短距离
重中之重:这个路径不一定能遍历到所有的点,但最小生成树可以
本蒟蒻感觉到的就这一点,欢迎各位大佬补充
画个祖传小图~
还有一个重点!、
最小生成树只适用于无向图
浅浅推导一下
如果要想遍历整个图,这一条边不能舍
因为这个边如果不走的话那么就遍历不到5号了
接下来进行排序,因为是最小生成树,所以先考虑权值小的边
最小的就是一号到三号,这条边要了
继续往下看,就应该考虑二号到三号了(因为四号到五号确定了。就不再特殊考虑了)
二号到三号此时还并未联通,所以这条边要了
接下来就是二号到一号
重点来力!
此时一号到二号已经处于联通状态(间接连通)
所以这条边不要
接下来考虑二号和四号,他们未联通,这条边要了
就差最后一条边了,就是三号到四号,此时三四号也已经联通(间接的间接连通)
所以也不要
整理一下,最后的生成树就是这样的:
如果你一个字一个字地看完了上面的内容,毋庸置疑你已经掌握了最小生成树的其中一种算法的思想(kruskal)
另外一种算法叫prim(因为本蒟蒻不太擅长而且教练也建议用kruskal,所以这篇文章就不做prim的介绍了)
思想理解了代码还不好写?
确实不太好写
最小生成树需要并查集的思想,之前做过介绍,大家可以看一下
以及链式前向星的讲解(因为和这篇文章是一起写的,比较仓促,不明白的随时评论区见)
因为之前讲过链式前向星的内容,这里就不赘述了
按照我们刚才的思想以及和并查集的集合,便可很轻易地写出代码
并查集的几个函数就不多说了直接上了
void make(){
for (int i=1;i<=n;i++){
f[i]=i;
h[i]=1;
}
}
int find(int x){
if (f[x]!=x){
return f[x]=find(f[x]);
}else{
return f[x];
}
}
void join(int x,int y){
if (x==y){
return;
}
if (h[x]>=h[y]){
f[y]=x;
h[x]+=h[y];
h[y]=0;
}else{
f[x]=y;
h[y]+=h[x];
h[x]=0;
}
}
接下来就是最重要的函数:kruskal!!!!
带着大家一步一步地推代码
框架写好:
int kruskal(){
}
按照我们最小生成树的原理,权值从小到大依次考虑
所以我们先排序
注意这里结构体排序需要写cmp函数
定义一个ans变量,表示最小生成树要的那些边的权值之和,也是最后返回的东西
第二步
循环m条边,每条边都取这条边的起点和终点,然后判断目前两点是否连通
怎么判断呢?
是的!利用并查集的find函数
寻找到两个点的祖先节点,如果相同,就是联通,则跳过
否则加入这条边
int ans=0;
make();
sort(edges+1,edges+1+m);
for(int i=1;i<=m;i++){
int a=find(edges[i].a),b =find(edges[i].b);
if (a==b){
continue;
}
join(a,b);
ans+=edges[i].w;
}
然后呢?
没有了
最小生成树就这么点内容
看到这里的你可能会觉得图论好简单
是的,图论都是模板,可他抽象是真的难,如果不给你算法标签,真的很难抽象
本蒟蒻推一个觉得不错的例题,感受一下
因为这题是我们OJ特有的题(撅着屁股炫耀)
所以就跟大家说一下概述,不把原题复制了
题目描述
A市某小区安装n台监控,现要将它们用网线连接起来。两台监控被连接是指它们有网线连接。由于监控所处的位置不同,因此不同的两台监控的连接费用是不同的。
我们采用数据的间接传输手段,即一台监控可以间接的通过若干台监控(作为中转)来实现与另一台监控的连接。
现在由你负责连接这些监控,任务是使任意两台监控都连通(不管是直接的或间接的)。
输入
第一行为整数n(2≤n≤100),表示监控的数目。此后的n行,每行n个整数。第x+1行y列的整数表示直接连接第x台监控和第y台监控的费用(费用不超过10000)
输出
一个整数,表示最小的连接费用。
Don't be shy
本蒟蒻第一次看这个玩意儿也很恶心,不过还算比较好抽象
最小生成树标志词:
最小费用
使得任意两个都联通
看到这些词,第一印象就是
啊!蒟蒻在csdn讲过!是最小生成树!
抽象出来了
代码不难了
还是那个原因,是我们自己的题,给AC代码也没用,所以本题仅做思路参考
最小生成数在图论中理解难度算★★★★,但是代码难度简直降维打击好吧,最多★★
制作不易,点个赞吧~