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

Kruskal 알고리즘 :

Kruskal 알고리즘은 연결된 네트워크의 최소 스패닝 트리를 찾는 또 다른 방법입니다.이 알고리즘의 아이디어는 작은 것에서 큰 것까지 가장자리를 추가하는 것입니다. 탐욕스러운 알고리즘입니다. 알고리즘의 시간은 주로 네트워크를 정렬하는 데 사용됩니다. 시간 복잡도는 O (eloge)이며, 간선 수가 적은 그래프의 최소 스패닝 트리를 찾는 데 적합합니다.

알고리즘 단계 :
1. 에지에 해당하는 포인트의 번호와 함께 에지 정보를 기록합니다
. 2. 에지 가중치별로 정렬
3. 두 포인트가 동일한 세트가 아닌 경우 매번 작은 에지에서 큰 에지로 에지를 가져 와서 병합합니다. 그렇지 않으면 계속해서 다음 에지를
봅니다 4. 에지 수가 n-1이면 순회가 종료되고 최소 스패닝 트리
획득됩니다 알고리즘 단계 :
1. 에지의 정보를 번호와 함께 기록합니다.
가장자리에 해당하는 점 2. 가장자리 가중치로 정렬
3 작은 가장자리에서 큰 가장자리로 이동할 때마다 두 지점이 동일하지 않으면 병합하고 그렇지 않으면 다음 가장자리를 계속 봅니다
. 4. 숫자가 가장자리 수는 n-1, 순회 끝 및 최소 스패닝 트리

Kruskal 알고리즘 템플릿 :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const int N = 100010;

typedef struct{
    
    
    int u;
    int v;
    int w;
} Edge;

Edge E[N];  //存边
int S[N];   //并查集
int n, e, minSum;	//n是点数,e是无向边的边数 

//路径压缩
int find(int x){
    
    
	if(S[x] < 0) return x;
	return S[x] = find(S[x]);
} 

//按秩归并
void Union(int root1, int root2){
    
    
	if(S[root1] < S[root2])
		S[root2] = root1;
	else if(S[root1] == S[root2]){
    
    
		S[root1]--;
		S[root2] = root1;
		}
	else{
    
    
		S[root1] = root2;
		}
} 

//按边权从小到大排序 
int cmp(const void *a, const void *b){
    
    
	return ((Edge*)a)->w - ((Edge*)b)->w;
} 

void Kruskal(){
    
    
	memset(S, -1, sizeof(S));
	qsort(E, e, sizeof(Edge), cmp);
	int cnt = 0, idx = 0;
	while(cnt != n - 1){
    
    	//共需要添加n-1条边  
		int x1 = E[idx].u, x2 = E[idx].v;
		int root1 = find(x1);
		int root2 = find(x2);
		if(root1 != root2){
    
    
			Union(root1, root2);
			minSum += E[idx].w;
			cnt++;
			}
		idx++;
		}
}

int main(void){
    
    
    scanf("%d %d", &n, &e);
    int a, b, c;
    for(int i = 0; i < e; i++){
    
    
    	scanf("%d %d %d", &a, &b, &c);
    	E[i].u = a, E[i].v = b, E[i].w = c;
    	}
    Kruskal();
    printf("%d\n", minSum);
    return 0;
}

추천

출처blog.csdn.net/mingjiweixiao/article/details/113871123