Minimum spanning tree---Kruskal algorithm (template)

ps: Explanation on station B

The basic idea of Kruskal's algorithm is to hide all edges initially, so that each vertex in the graph becomes a connected block by itself. Then perform the following steps:

  1. Sort all edges from smallest to largest.
  2. Test all edges according to the edge weight from small to large. If the two vertices connected by the currently tested edge are not in a connected block, add this test edge to the current minimum spanning tree; otherwise, discard the edge.
  3. Perform step 2 until the number of edges in the minimum spanning tree is less than the total number of vertices minus one, or the test is over for all edges. When the number of edges of the minimum spanning tree is less than the total number of vertices minus one at the end, the graph is not connected.

template:

struct node{
    
    	//存储边及边权
	int u,v,dis;
}e[M];	
bool cmp(node x,node y){
    
    	//sort的比较函数
	return x.dis < y.dis;
}
int father[N];	//存放每个节点的父亲节点的father数组
int findfather(int v){
    
    	//查找节点的父亲节点
	if(father[v] == v) 	return v;
	else{
    
    
		int F = findfather(father[v]);
		father[v] = F;
		return F;
	}
}
int Kruskal(int n,int m){
    
    
	int ans = 0,num_edge = 0;
	//ans为所求最小生成树的边权之和,num_edge为当前生成树的边数
	for(int i = 0;i< n;i++){
    
    		//father[]初始化,注意节点的范围(以0 - n为例)
		father[i] = i;
	}
	sort(e,e+m,cmp);	//对边的权值按照从小到大排序
	for(int i = 0;i< m;i++){
    
    
		int fu = findfather(e[i].u);
		int fv = findfather(e[i].v);
		if(fu != fv){
    
    	//如果两个节点的父亲节点不同,则将次边加入最小生成树
			ans+= e]i].dis;	//加上边权
			father[fu] = fv;
			num_edge++;
			if(num_edge == n-1)	//如果最小生成树的边数目达到节点数减一,就退出
				break;
		}
	}
	return ans;
}

enter:

6 10
0 1 4
0 4 1
0 5 2
1 2 6
1 5 3
2 3 6
2 5 5
3 4 4
3 5 5
4 5 3

The first line is the number of vertices and the number of edges. The
next m line is the output of two nodes and the edge weights from node to node
:

15

Code:

#include<bits/stdc++.h>
using namespace std;
int n,m,father[100];
struct node{
    
    	//边的两个顶点和边权 
	int u,v,dis;
}e[100];
bool cmp(node x,node y){
    
    	//sort函数的比较函数 
	return x.dis<y.dis;
}
int findf(int v){
    
    	//并查集的寻找函数 
	if(father[v] == v)	return v;
	else{
    
    
		int F = findf(father[v]);	//注意这里函数的参数是father[v] 
		father[v] = F;
		return F;
	}
}

int Kruskal(){
    
    
	int re = 0,num_edge = 0;
	//re为边权之和,num_edge为目前生成树中的边 
	for(int i = 0;i<n;i++){
    
     	//father数组初始化 
		father[i] = i;
	}
	sort(e,e+m,cmp);	//对边从小到大排序 
	for(int i = 0;i<m;i++){
    
    
		int fu = findf(e[i].u);	//找到父亲节点 
		int fv = findf(e[i].v);
		if(fv != fu){
    
    
			re += e[i].dis;	 
			father[fu] = fv;
			num_edge++;
			if(num_edge == n - 1 ) //如果边的数量达到了生成树的最大边数 
				break;
		}
	}
	return re;
}

int main(){
    
    
	freopen("a.txt","r",stdin);
	int u,v,k;
	cin>>n>>m;
	for(int i = 0;i<m;i++){
    
    	//读入数据 
		cin>>u>>v>>k;
		e[i].u = u;
		e[i].v = v;
		e[i].dis = k;
	}
	cout<<Kruskal()<<endl;
	return 0;
} 

end.

Guess you like

Origin blog.csdn.net/m0_45210226/article/details/106060031