最小生成树(Kruskal算法及相关例题)

1.Kruskal算法概念以及基本思路

(1)概念:

克鲁斯卡尔算法是求连通网的最小生成树的另一种方法。它的时间复杂度为O(ElogE)(E是图G的边的总数),适合于求边稀疏的网的最小生成树 。

其基本思想是:假设连通网G,令最小生成树的初始状态为只有n个顶点且没有任何一条边的图T,概述图中每个顶点自成一个连通分量。在E中选择代价最小(即距离最短)的边,若该边依附的顶点分别在T中不同的连通分量上,则将此边加入到T中;否则,舍去此边而选择下一条代价最小的边。换而言之就是在整个图找最短的边,从短到长一次寻找,若没有连通,则进行连通,若已经连通,则放弃这个边,去寻找下一个,知道变成连通图

(2)基本思路:

从它的基本思想我们可以得出做题时的基本思路:

1.首先创建一个一维数组,用于判断这个点是否连通,每个数组的初始值都对应自己的下标

2.创建一个结构体,存储位置信息,以及之间的长度

3.通过快排进行排序,将路径最短的排在前面

4.根据题解去寻找最小生成树

2.相关例题

第一题:最小生成树

 

题解:这题就是最基本的最小生成树问题,没有什么难度

#include<bits/stdc++.h>
using namespace std;int n,m;//n个结点和m条边
struct lu//代表路径的结构体
{int start;//起始节点int end1;//终止结点int l;//路径长度
}q[200005];
int f[50005];//用于判断是否连通的数组
int count1;//统计已经连通几条边
long long sum;//总长度int cha(int x)//查,判断是否属于同一个根节点
{if(f[x]==x)return x;return cha(f[x]);
}void bing(int root1,int root2)//并,将根节点并在一起
{if(root1==root2)return;f[root2]=root1;
}bool cmp(lu a,lu b)//路径要根据路径长度进行比较
{return a.l<b.l;//快排顺序,从小到大排列路径长度
}int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){f[i]=i;//将根节点设置为自己}for(int i=0;i<m;i++){scanf("%d%d%d",&q[i].start,&q[i].end1,&q[i].l);}sort(q+1,q+m+1,cmp);//快排for(int i=0;i<m;i++){if(cha(q[i].start)==cha(q[i].end1))//如果已经并在一起就直接跳过continue;bing(cha(q[i].start),cha(q[i].end1));sum+=q[i].l;count1++;if(count1==n-1)//当满足了连通图,这个是连通图的性质,边数=顶点数-1break;}if(count1<n-1)//如果是非连通图{printf("orz");return 0;}printf("%d",sum);return 0;
}

第二题:拆地毯

题解:这题其实就是最小生成树的地方略变一点儿,求的是最大生成树,我们要找的是最长的长度,那么我们只需要改变一下快排的方式即可

AC代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,k;
struct lu
{int start;int end1;int l;
}q[100005];
int f[100005];
int count1;
int sum;
int cha(int x)
{if(f[x]==x)return x;return cha(f[x]);
}
void bing(int root1,int root2)
{if(root1==root2)return ;f[root2]=root1;
}
bool cmp(lu a,lu b)
{return a.l>b.l;//改变一下快排的方式
}
int main()
{scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=n;i++)f[i]=i;for(int i=0;i<m;i++){scanf("%d%d%d",&q[i].start,&q[i].end1,&q[i].l);}sort(q,q+m,cmp);for(int i=0;i<m;i++){if(cha(q[i].start)==cha(q[i].end1))continue;bing(cha(q[i].start),cha(q[i].end1));count1++;sum+=q[i].l;if(count1==k)//当保留的地毯满足保留的个数结束就可以break;}printf("%d",sum);return 0;
}

第三题:无线通讯网

题解:也是最小生成树类的题目,但是没什么的,唯一改变的地方就是因为这个地方不是求路径和,而是卡的最小的无线电所需要的距离,也就是卡的极限最小值

#include<bits/stdc++.h>
using namespace std;
int s,p;
int x[505],y[505];
int f[1000005];
struct lu
{int start;int end1;double l;
}q[2000005];
int count1;
double sum;
int cha(int x)
{if(f[x]==x)return x;return cha(f[x]);
}
void bing(int root1,int root2)
{if(root1==root2)return ;f[root2]=root1;	
}
bool cmp(lu a,lu b)
{return a.l<b.l;
}
int main()
{int flag=0;scanf("%d%d",&s,&p);for(int i=1;i<=p;i++)f[i]=i;for(int i=1;i<=p;i++){scanf("%d%d",&x[i],&y[i]);for(int j=1;j<i;j++){flag++;q[flag].start=i;q[flag].end1=j;q[flag].l=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));}}sort(q+1,q+1+flag,cmp);for(int i=1;i<=flag;i++){if(cha(q[i].start)==cha(q[i].end1))continue;sum=q[i].l;//长度就是那个极限的值bing(cha(q[i].start),cha(q[i].end1));count1++;if(count1==p-s)//当满足了结束条件break;}printf("%.2lf",sum);return 0;
}

第四题:营救

题解:也是最小生成树的题目和第三题其实一样,只不过排的是拥挤度

AC代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,s,t;
struct lu
{int start;int end1;int l;
}q[20005];
int f[10005];
int count1;
int sum;
int cha(int x)
{if(f[x]==x)return x;return cha(f[x]);
}
void bing(int root1,int root2)
{if(root1==root2)return ;f[root2]=root1;
}
bool cmp(lu a,lu b)
{return a.l<b.l;
}
int main()
{scanf("%d%d%d%d",&n,&m,&s,&t);for(int i=1;i<=n;i++)f[i]=i;for(int i=0;i<m;i++){scanf("%d%d%d",&q[i].start,&q[i].end1,&q[i].l);}sort(q,q+m,cmp);for(int i=0;i<m;i++){bing(cha(q[i].start),cha(q[i].end1));sum=q[i].l;if(cha(s)==cha(t)){break;}}printf("%d",sum);return 0;
}

第五题:买礼物

题解:这题有一个坑,就是有可能绑定在一起买比单个买还要贵,因此我们在进行价值的计算时需要有一个判断

#include<bits/stdc++.h>
using namespace std;
int a,b;
struct wu
{int x,y;int w;
}q[250005];
int f[505];
int sum;
int count1;
int cha(int x)
{if(f[x]==x)return x;return cha(f[x]);
}
void bing(int root1,int root2)
{if(root1==root2){return ;}f[root2]=root1;
}
bool cmp(wu a,wu b)
{return a.w<b.w;
}
int main()
{scanf("%d%d",&a,&b);sum=a;for(int i=1;i<=b;i++)f[i]=i;for(int i=1;i<=b;i++){for(int j=1;j<=b;j++){count1++;scanf("%d",&q[count1].w);q[count1].x=i;q[count1].y=j;if(q[count1].w==0)q[count1].w=a;}}sort(q+1,q+1+count1,cmp);for(int i=1;i<=count1;i++){if(cha(q[i].x)==cha(q[i].y))continue;bing(cha(q[i].x),cha(q[i].y));sum+=min(q[i].w,a);//去优惠价格和原价格的小值}printf("%d",sum);return 0;
}

 第六题:Building Roads S

 题解:这题也是很简单的和无线电那个在处理坐标的方式差不多,但是恶心的地方在于精度的把控,需要在原本的精度上更加细致不然还是会WA,血的教训,也是一开始就中计了啊,大意了,没有闪

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/471731.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python 异常处理语句

Python 是一门广泛应用于软件开发和数据科学领域的高级编程语言。在编写程序的过程中&#xff0c;难以避免地会遇到各种错误和异常情况。Python 提供了丰富的异常处理机制&#xff0c;帮助开发者优雅地应对异常&#xff0c;使程序具有更好的稳定性和可靠性。本文将深入探讨 Pyt…

生成式AI相关知识记录

一、简述开发步骤 开发一个生成式AI模型通常涉及以下步骤&#xff1a; 1. **需求分析与目标设定**&#xff1a; - 确定应用领域和目标&#xff0c;例如文本生成、图像生成、音乐创作等。 - 分析应用场景的具体需求&#xff0c;包括输出质量、速度、多样性、可控性等因素…

SORA:OpenAI最新文本驱动视频生成大模型技术报告解读

Video generation models as world simulators&#xff1a;作为世界模拟器的视频生成模型 1、概览2、Turning visual data into patches&#xff1a;将视觉数据转换为补丁3、Video compression network&#xff1a;视频压缩网络4、Spacetime Latent Patches&#xff1a;时空潜在…

LEETCODE 164. 破解闯关密码

class Solution { public:string crackPassword(vector<int>& password) {vector<string> password_str;for(int i0;i<password.size();i){password_str.push_back(to_string(password[i]));}//希尔排序int gappassword.size()/2;while(gap>0){for(int i…

安卓TextView 拖动命名

需求&#xff1a;该布局文件使用线性布局来排列三个文本视图和一个按钮&#xff0c;分别用于显示两个动物名称以及占位文本视图。在占位文本视图中&#xff0c;我们为其设置了背景和居中显示样式&#xff0c;并用其作为接收拖放操作的目标 效果图&#xff1b; 实现代码 第一布…

NSSCTF Round#18 RE WP 完整复现

1. GenshinWishSimulator 恶搞原神抽卡模拟器 看到软件的界面&#xff0c;大致有三种思路&#xff1a; 修改石头数量一直抽&#xff0c;如果概率正常肯定能抽到&#xff08;但是估计设置的概率是0&#xff09;在源码里找flag的数据把抽卡概率改成100%直接抽出来 Unity逆向&am…

mpack简明教程

文章目录 摘要MessagePack简介MPACK的简单使用在定长的buffer存储不定长的数据读取截断的数据 摘要 本文先简单介绍MessagePack的基本概念。 然后&#xff0c;介绍一个MessagePack C API - MPack的通常使用。 接着尝试对MPack截断数据的读取。 注&#xff1a;本文完整代码见…

springboot187社区养老服务平台的设计与实现

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

优化策略模式,提高账薄显示的灵活性和扩展性

接着上一篇文章&#xff0c;账薄显示出来之后&#xff0c;为了提高软件的可扩展性和灵活性&#xff0c;我们应用策略设计模式。这不仅仅是为了提高代码的维护性&#xff0c;而是因为明细分类账账薄显示的后面有金额分析这个功能&#xff0c;从数据库后台分析及结合Java语言特性…

记录一次涩涩情侣飞行棋密码破解

注本公众号&#xff0c;长期推送技术文章 知攻善防实验室 红蓝对抗&#xff0c;Web渗透测试&#xff0c;红队攻击&#xff0c;蓝队防守&#xff0c;内网渗透&#xff0c;漏洞分析&#xff0c;漏洞原理&#xff0c;开源 工具&#xff0c;社工钓鱼&#xff0c;网络安全。 81篇原…

【后端高频面试题--Nginx篇】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;后端高频面试题 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 后端高频面试题--Nginx篇 往期精彩内容什么是Nginx&#xff1f;为什么要用Nginx&#xff1f;为…

「递归算法」:两两交换链表中的节点

一、题目 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4] 输出&#xf…