Camino real_Ejemplo 11.4 Proyecto desbloqueado (Kruskal)

Árbol de expansión mínimo

En un gráfico conectado no dirigido , si hay un subgrafo conectado que contiene todos los vértices y algunos bordes del gráfico original, y el subgrafo no tiene bucles, este subgrafo se denomina árbol de expansión del gráfico original. En un gráfico conectado ponderado no dirigido, la suma más pequeña de los pesos de los bordes en todos los árboles de expansión se denomina árbol de expansión mínimo .

Kruskal

Proceder de la siguiente:

  • Inicialmente, todos los vértices pertenecen a un conjunto aislado.
  • Atraviesa todos los bordes de acuerdo con el peso del borde creciente. Si los dos vértices de los bordes obtenidos pertenecen a conjuntos diferentes, los dos puntos se fusionan en un conjunto y el borde es un borde en el árbol de expansión mínimo
  • Después del recorrido, si el gráfico original está conectado, los bordes y puntos seleccionados constituyen el árbol de expansión mínimo; de lo contrario, el árbol de expansión mínimo no existe.

Clave:

int Kruskal(int n,int edgeNumber)
{
    
    
	int sum=0;
	sort(edge,edge+edgeNumber,cmp);//按照边权从小到大排序
	for(int i=0;i<edgeNumber;++i)
	{
    
    
		Edge current=edge[i];
		if(Find(current.from)!=Find(current.to))//如果这个两个节点原来不在一个集合中,合并 
		{
    
    
			Union(current.from,current.to);
			sum+=current.length;
		}
	 }
	 return sum; 
}

Código

Significado de la pregunta: Dados n puntos, n * (n-1) / 2 caminos, encuentre la distancia más pequeña para conectar todos los puntos.

#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN=100; 
struct Edge{
    
    
	int from;
	int to;
	int length;
};
Edge edge[MAXN*MAXN];
int father[MAXN];
int height[MAXN];
void Initial(int n)
{
    
    
	for(int i=0;i<n;++i)
	{
    
    
		father[i]=i;
		height[i]=0;
	}
}
//寻找根节点 
int Find(int x) 
{
    
    
	if(x!=father[x])
		father[x]=Find(father[x]);
	return father[x]; 
}
void Union(int x,int y) 
{
    
    
	x=Find(x);
	y=Find(y);
	if(x!=y)//发现x y不属于一个集合,此时由于输入了x指向y这条边,所以要合并集合 
	{
    
    
		if(height[x]<height[y])
			father[x]=y;
		else if(height[y]<height[x])
			father[y]=x;
		else{
    
    
			father[x]=y;
			++height[y];
		}
	}
}
bool cmp(Edge a,Edge b)
{
    
    
	return a.length<b.length;
 } 
int Kruskal(int n,int edgeNumber)
{
    
    
	int sum=0;
	sort(edge,edge+edgeNumber,cmp);//按照边权从小到大排序
	for(int i=0;i<edgeNumber;++i)
	{
    
    
		Edge current=edge[i];
		if(Find(current.from)!=Find(current.to))//如果这个两个节点原来不在一个集合中,合并 
		{
    
    
			Union(current.from,current.to);
			sum+=current.length;
		}
	 }
	 return sum; 
}
int main()
{
    
    
	int n;//村庄数
	while(cin>>n)
	{
    
    
		if(n==0) break;
		int edgeNumber=(n-1)*n/2;
		Initial(edgeNumber);
		for(int i=0;i<edgeNumber;++i)
		{
    
    
			cin>>edge[i].from>>edge[i].to>>edge[i].length;
		}
		int answer=Kruskal(n,edgeNumber);
		cout<<answer<<endl;
	 } 
	  
}

Supongo que te gusta

Origin blog.csdn.net/weixin_45019830/article/details/115032051
Recomendado
Clasificación