Árbol de expansión mínimo --- Algoritmo de Kruskal (plantilla)

ps: Explicación sobre la estación B

La idea básica del algoritmo de Kruskal es ocultar todos los bordes inicialmente, de modo que cada vértice del gráfico se convierta en un bloque conectado por sí mismo. Luego, realice los siguientes pasos:

  1. Ordene todos los bordes de menor a mayor.
  2. Pruebe todos los bordes de acuerdo con el peso del borde de pequeño a grande. Si los dos vértices conectados por el borde actualmente probado no están en un bloque conectado, agregue este borde de prueba al árbol de expansión mínimo actual; de lo contrario, descarte el borde.
  3. Realice el paso 2 hasta que el número de aristas en el árbol de expansión mínimo sea menor que el número total de vértices menos uno, o la prueba haya terminado para todas las aristas. Cuando el número de aristas del árbol de expansión mínimo es menor que el número total de vértices menos uno al final, el gráfico no está conectado.

modelo:

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

entrar:

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

La primera línea es el número de vértices y el número de aristas. La
siguiente línea m es la salida de dos nodos y los pesos de las aristas de un nodo a otro
:

15

Código:

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

final.

Supongo que te gusta

Origin blog.csdn.net/m0_45210226/article/details/106060031
Recomendado
Clasificación