欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

简单易懂的Kruskal算法教程 - 配有详尽注释的完整代码示例

最编程 2024-02-16 11:49:20
...
#include<bits/stdc++.h> //POJ不支持 #define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增 #define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。 #define pb push_back #define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0) #define fi first #define se second #define mp make_pair using namespace std; const int inf = 0x3f3f3f3f;//无穷大 const int maxn = 1e5;//最大值。 typedef long long ll; typedef long double ld; typedef pair<ll, ll> pll; typedef pair<int, int> pii; //*******************************分割线,以上为自定义代码模板***************************************// struct edge{ int s;//边的起始顶点。 int e;//边的终端顶点。 int w;//边权值。 bool operator < (const edge &a){ return w<a.w; } }; edge temp[maxn];//临时数组存储边。 int verx[maxn];//辅助数组,判断是否连通。 edge tree[maxn];//最小生成树。 int n,m;//n*n的图,m条边。 int cnt;//统计生成结点个数,若不满足n个,则生成失败。 int sum;//最小生成树权值总和。 void print(){ //打印最小生成树函数。 cout<<"最小生成树的权值总和为:"<<sum<<endl; rep(i,0,cnt-1){ cout<<tree[i].s<<" "<<tree[i].e<<"边权值为"<<tree[i].w<<endl; } } void Kruskal(){ rep(i,1,n) verx[i]=i;//这里表示各顶点自成一个连通分量。 cnt=0;sum=0; sort(temp,temp+m);//将边按权值排列。 int v1,v2; rep(i,0,m-1){ v1=verx[temp[i].s]; v2=verx[temp[i].e]; if(v1!=v2){ tree[cnt].s=temp[i].s;tree[cnt].e=temp[i].e;tree[cnt].w=temp[i].w;//并入最小生成树。 rep(j,1,n){ //合并v1和v2的两个分量,即两个集合统一编号。 if(verx[j]==v2)verx[j]=v1; //默认集合编号为v2的改为v1. } sum+=tree[cnt].w; cnt++; } } //结束双层for循环之后得到tree即是最小生成树。 print(); } int main(){ //freopen("in.txt", "r", stdin);//提交的时候要注释掉 IOS; while(cin>>n>>m){ int u,v,w; rep(i,0,m-1){ cin>>u>>v>>w; temp[i].s=u;temp[i].e=v;temp[i].w=w; } Kruskal(); } return 0; }