최소 스패닝 트리 --- Kruskal 알고리즘 (템플릿)

추신 : 스테이션 B에 대한 설명

Kruskal 알고리즘 의 기본 아이디어는 처음에는 모든 모서리를 숨기고 그래프의 각 정점이 자체적으로 연결된 블록이되도록하는 것입니다. 그런 다음 다음 단계를 수행하십시오.

  1. 가장 작은 것부터 가장 큰 것까지 모든 모서리를 정렬합니다.
  2. 작은 것부터 큰 것까지 가장자리 가중치에 따라 모든 가장자리를 테스트합니다. 현재 테스트 된 가장자리로 연결된 두 정점이 연결된 블록에 없으면이 테스트 가장자리를 현재 최소 스패닝 트리에 추가하고 그렇지 않으면 가장자리를 버립니다.
  3. 최소 스패닝 트리의 가장자리 수가 총 정점 수에서 1을 뺀 값보다 적거나 모든 가장자리에 대한 테스트가 끝날 때까지 2 단계를 수행합니다. 최소 스패닝 트리의 간선 수가 총 정점 수에서 끝을 뺀 값보다 적 으면 그래프가 연결되지 않습니다.

주형:

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;
}

시작하다:

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

첫 번째 줄은 정점 수와 가장자리 수이고
다음 m 줄은 두 노드의 출력과 노드 간 가장자리 가중치입니다
.

15

암호:

#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;
} 

종료.

추천

출처blog.csdn.net/m0_45210226/article/details/106060031