克鲁斯卡尔算法(Kruskal)
- 克鲁斯卡尔
模板题目:
图中的6个顶点分别代表6个村庄,线段的权值代表村庄之间的距离。请问如何找到最短的路径来访问每一个村庄,且每个村庄只访问一次。
关键:
- 一个存储边的结构体(edgetype),包括起点(from)终点(to)权值(weight)
- 一个存储树的结构体(edggragh),这棵树包含:边的个数(edgenum),顶点的个数(vesnum),包含顶点序号的数组(顶点数组:vesn[100]),边的结构体(edgen[100])
- 三个函数
(1)初始化inigragh:
Step1:用一个结构体变量(Myedge)存储边的信息包括:顶点数(vexn),边数(edgen),每个边的权值。
Step2:把结构体变量(Myedge)按找权值(weight)进行排序(这里使用冒泡法排序)
Step3:把排好序的结构体变量(Myedge)汇入到树(Mygragh)中,并初始化树的顶点数组vesn[100])
(2) 构建生成树并输出waygragh:
Step1:新建一个容器(mst)来存放新的生成树
Step2:新建一个数组(root)来存放每个节点的根,并把他初始化(-1),以表示在构建前,每个节点都是一棵独立的树,根节点为他本身
Step3:根据每条边的权值从小到大寻找每一条边的起始节和终点节点(因为在上一个函数中已经排好序,所以实际上是顺序查找),并判断起始节点和终点节点的根节点是否相同(是否能构成环),这一步需要引用寻找根节点的函数(soortfind)
Step4:如果不能构成环,就把这条边的数据放入容器mst中
Step5:如果检查完了所有的边就跳出
Step6:输出mst
(3) 寻找根节点soortfind:
接收顶点的序号,借助于while寻找根,具体实现请看代码部分和注释
下面的代码有一点问题,在编译器中前几次运行数值不定,多运行几次后趋于稳定
#include<bits/stdc++.h> using namespace std; struct edgetype//存储边的结构体 { int from,to; int weight; }; struct edggragh//存储树的结构体 { int vexs[100]; struct edgetype edges[100]; int vexnum,edgenum; }; void inigragh(struct edggragh *Mygragh);//初始化 声明 void waygragh(struct edggragh *Mygragh);//构建生成树并输出 声明 int rootfind(int parent[],int v);//寻找根节点的 声明 int main()//主函数只调用子函数 { edggragh Myedge; inigragh(&Myedge); waygragh(&Myedge); system("pause"); return 0; } //初始化 void inigragh(struct edggragh *Mygragh) { int vexn; int edgen; cout<<"请输入顶点个数:"; cin>>vexn; cout<<"请输入边的个数:"; cin>>edgen; edgetype *Myedge=new edgetype[edgen]; cout<<"请输入各个边的起点,终点和权值(用空格隔开):"<<endl; for(int i=0;i<edgen;i++) { cin>>Myedge[i].from>>Myedge[i].to>>Myedge[i].weight; } for(int i=0;i<edgen;i++)//冒泡排序 for(int j=0;j<edgen-1-i;j++) { edgetype temp; if(Myedge[j].weight>Myedge[j+1].weight) { temp=Myedge[j]; Myedge[j]=Myedge[j+1]; Myedge[j+1]=temp; } } (*Mygragh).vexnum=vexn;//对结构体变量(Myedge) 进行初始化 (*Mygragh).edgenum=edgen; for(int i=0;i<edgen;i++) { (*Mygragh).edges[i]=Myedge[i]; } for(int i=0;i<vexn;i++) { (*Mygragh).vexs[i]=i; } } //构建生成树并输出 void waygragh(struct edggragh *Mygragh) { edgetype *mst=new edgetype[(*Mygragh).vexnum];//新建一个容器(mst)来存放新的生成树 int *root=new int[(*Mygragh).vexnum];//新建一个数组(root)来存放每个节点的根 for(int i=0;i<(*Mygragh).vexnum;i++)//初始化 { root[i]=-1; } int num=0;//控制mst容器的下标 for(int i=0;i<(*Mygragh).edgenum;i++) { //引用soortfind函数寻找根节点 int v1=rootfind(root,(*Mygragh).edges[i].from); int v2=rootfind(root,(*Mygragh).edges[i].to); // 如果不能构成环,就把这条边的数据放入容器mst中 if(v1!=v2) { mst[num]=(*Mygragh).edges[i]; root[v2]=v1; num++; } //如果检查完了所有的边就跳出 if(num==(*Mygragh).vexnum-1) break; } //输出mst for(int i=0;i<num;i++) { cout<<"("<<mst[i].from<<","<<mst[i].to<<")"<<mst[i].weight<<endl; } } //寻找根节点 int rootfind(int parent[],int v) { int v1=v; while(parent[v1]>-1) v1=parent[v1]; return v1; }
正确的模板:
void Kruskal(int n,int m) { int i,sum=0,ans=0; for(i=1;i<=n;i++) { pre[i]=i; } for(i=1;i<=m;i++) { int x=root(s[i].u); int y=root(s[i].v); if(x!=y) { sum++; ans+=s[i].w; pre[x]=pre[y]; if(sum == n) break; } } cout<<ans<<endl; }
例题:
http://10.64.27.5:8888/p/P32?tid=61eb7a0dc3d405e68f6392d7
ac代码:
#include<bits/stdc++.h> long long zu[1000]; long long m,n; using namespace std; struct node { long long s; long long e; long long w; }; node edge[1000]; bool cmp(struct node x,struct node y) { return x.w<y.w; } int root(long long a) { int r=a; while(zu[r]!=r) { r=zu[r]; } int b=a,c; while(zu[b]!=r)//减少运算量的步骤,把每个节点都指向它的根节点 { c=zu[b]; zu[b]=r; b=c; } return r; } void kkk(long long m,long long n) { node mst[100]; long long i,count=0; long long ans=0; for(i=0;i<n;i++) { int v1=root(edge[i].s); int v2=root(edge[i].e); if(v1!=v2) { mst[count]=edge[i]; count++; ans+=edge[i].w; zu[v1]=v2; } if(count==m) break; } for(int i=0;i<count;i++) cout<<mst[i].s<<mst[i].e<<mst[i].w<<endl; cout<<ans<<endl; } int main() { cin>>m>>n; for(int i=0;i<n;i++) { cin>>edge[i].s>>edge[i].e>>edge[i].w; } for(int i=0;i<m;i++) { zu[i]=i; } sort(edge,edge+n+1,cmp);//取决于边数 kkk(m,n); return 0; }
简单的对以前在word中的算法笔记进行整理,自用,参考标注不完整,侵删
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律