【模板】最小生成树-Kruskal

本文详细介绍了Kruskal算法的两种实现方式,一种使用数组进行操作,另一种使用结构体,均实现了对加权图的最小生成树的构建。通过洛谷p3366题例展示了算法的具体应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

两种写法

第一种:使用数组

/*
时间复杂度:O(nlogn) 
*/
#include<bits/stdc++.h>
using namespace std;
#define MAX 200000+10
int n,m;	//n:结点的数量  m:边的数量 
int u[MAX],v[MAX],w[MAX],r[MAX],p[MAX];	//u[i]v[i]第i条边的两端点,w[i]第i条边的权值,r[i]第i小的边的序号,p[i]并查集 
int cmp(const int i, const int j) { return w[i] < w[j]; } 		//间接排序函数
int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }	//并查集的find
int Kruskal() 
{
	int ans = 0;
	for (int i = 0; i <= n; i++) p[i] = i; 	//初始化并查集
	for (int i = 0; i <= m; i++) r[i] = i; 	//初始化边序号
	sort(r, r + m, cmp); 	//给边排序
	for (int i = 0; i < m; i++) 
	{
		int e = r[i]; 		//找出当前边两个端点所在集合编号
		int x = find(u[e]); 
		int y = find(v[e]);
		if (x != y) 		//如果在不同集合,合并
		{ 
			ans += w[e]; 
			p[x] = y; 
		} 
	}
	return ans;
}
int main()
{
	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		cin>>u[i]>>v[i]>>w[i]; 
	}
	cout<<Kruskal()<<endl;
	return 0;
}
/*
洛谷 p3366 
输入:
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出:
7 
*/

第二种:使用结构体

/*
时间复杂度:O(nlogn) 
*/
#include<bits/stdc++.h>
using namespace std;
#define Max 200000+10
struct Edge
{
	int v,w,cost;
};
Edge a[Max];
int n,m,ans=0,p[Max];
bool cmp(Edge x,Edge y)
{
	return x.cost<y.cost;
}
int find(int x)
{
	return x==p[x]?x:p[x]=find(p[x]);
}
void Kruskal()
{
	for(int i=0;i<=n;i++)	p[i]=i;	//初始化并查集 
	sort(a,a+m,cmp);				//按照边的大小排序 
	int k=0,z=0;					//k为已经选择的边数,z为当前选择的边 
	ans=0;
	while(k!=n-1)			//选择出n-1条边,即为最小生成树 
	{
		int x=find(a[z].v);
		int y=find(a[z].w);
		if(x!=y)
		{
			p[x]=y;			//合并并查集 
			ans+=a[z].cost;
			k++;
		}
		z++;
	} 
}
int main()
{
	
	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		cin>>a[i].v>>a[i].w>>a[i].cost;
	}
	Kruskal();
	cout<<ans<<endl;
	return 0;
} 
/*
洛谷 p3366 
输入:
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出:
7 
*/

 

### Kruskal Algorithm Minimum Spanning Tree Code Template Kruskal算法用于寻找图中的最小生成树,通过按权重升序处理所有边并仅当连接两个不同集合的节点时才添加该边来构建最小生成树。以下是使用C++实现Kruskal算法的一个通用模板: ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; struct Edge { int u, v; long long weight; }; class DisjointSet { public: vector<int> parent, rank; DisjointSet(int n) : parent(n), rank(n, 0) { for (int i = 0; i < n; ++i) { parent[i] = i; } } int find(int x) { if (parent[x] != x) { parent[x] = find(parent[x]); } return parent[x]; } void Union(int x, int y) { int rootX = find(x); int rootY = find(y); if (rootX != rootY) { if (rank[rootX] > rank[rootY]) { parent[rootY] = rootX; } else if (rank[rootX] < rank[rootY]) { parent[rootX] = rootY; } else { parent[rootY] = rootX; rank[rootX]++; } } } }; long long kruskal(vector<Edge>& edges, int vertices) { sort(edges.begin(), edges.end(), [](const Edge& a, const Edge& b) {return a.weight < b.weight;} ); DisjointSet ds(vertices); long long mstWeight = 0; for(auto &edge : edges){ int set_u = ds.find(edge.u); int set_v = ds.find(edge.v); if(set_u != set_v){ cout << "Edge included (" << edge.u << ", " << edge.v << ") with weight " << edge.weight << endl; mstWeight += edge.weight; ds.Union(set_u,set_v); } } return mstWeight; } // Example usage of the function. /* int main() { int V = 4; // Number of vertices in graph vector<Edge> E = {{0, 1, 10}, {0, 2, 6}, {0, 3, 5}, {1, 3, 15}, {2, 3, 4}}; // Edges and their weights cout << "The total weight of MST is: " << kruskal(E,V)<<endl; } */ ``` 此代码定义了一个`DisjointSet`类来进行路径压缩和按秩合并操作,并实现了`kruskal()`函数以计算给定无向加权图中MST的总成本[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值