Estructura de datos / teoría de grafos: problema de árbol de expansión mínimo

Estructura de datos / teoría de grafos: problema de árbol de expansión mínimo

1. Descripción del problema

El árbol de expansión de un gráfico es un subgráfico que contiene todos los vértices y es un árbol. Un gráfico puede tener muchos árboles de expansión. El problema del árbol de expansión es uno de los problemas típicos resueltos por la teoría de redes, y hay muchos campos de aplicación.
Aplicación: Minimizar el circuito de soldadura requerido para conectar una serie de conectores en la placa de circuito; Minimizar el circuito requerido para establecer una red telefónica entre varias ciudades.

Dos, implementación de algoritmo

1. Algoritmo Prim

Idea
del algoritmo : el algoritmo de Prim es un algoritmo codicioso. Tome cualquier vértice v en la gráfica como la raíz del árbol de expansión y luego agregue un nuevo vértice w al árbol de expansión. Debe haber una arista entre el vértice añadido w y el vértice v ya en el árbol de expansión, y el peso de esta arista toma el valor más pequeño entre las aristas entre todos los vértices vy w conectados. Luego continúe agregando vértices al árbol de expansión hasta que haya n vértices en el árbol de expansión.

Implementación de pseudocódigo:

void Prim(Graph<string>* G, int* D, int s)
{
    
    
	// Prim's MSTalgorithm构造最小生成树算法
	int V[G->n()];// Store closest vertex 存储最近节点
	int i, w;
	for (i=0;i<G->n(); i++)
	{
    
    // Process the vertices 处理节点
	int v =minVertex(G, D);
	G->setMark(v, VISITED);
	if (v != s)
		AddEdgetoMST(G,V[v], v);// Add edge to MST 向MST中添加边
	if (D[v] ==INFINITY) return;// Unreachable vertices 不可达节点
	for(w=G->first(v); w<G->n(); w = G->next(v,w))
	if (D[w]> G->weight(v,w))
		{
    
    D[w] =G->weight(v,w);// Update distance 更新距离
		V[w] =v;// Where it came from记录节点
		}
	}
}

Función minVertex:

// Find min cost vertex寻找未访问的最短距离顶点
int minVertex(Graph* G,int* D)
{
    
    
	int i,V;
	// Set v to an unvisited vertex
	for(i=0;i<G->n();i++)
	if(G->getMark(i)==UNVISITED)
	{
    
    v=i;break;}
	// Now find smallest D va lue
	for(i++;i<G->n0;i++)
	if((G->getMark(i)==UNVISITED)&&(i<D[v1]))
	v=i;
	return V;
}

Algoritmo prim implementado por cola de prioridad:

void Prim(Graph* G, int* D, int s)
{
    
    
	int i, v,w; // The current vertex
	int V[G-n()]; // Who's closest
	DijkElem temp;
	DijkElem E[G->e()]; // Heap array with lots of space 
	temp.distance = 0;
	temp.vertex = s;
	E[0] = temp; // Initialize heap array
	minheap< DijkElem,DDComp> H(E, 1, G->e()); // Create the heap
	for (i=0; i<G->n(); i++)
	{
    
    // Now build MST
		do
		{
    
    if (!H.removemin(temp)) return;
		v = temp.vertex;
		} while (G.getMark(v) == VISITED);
	G->setMark(v, VISITED);
	if (v != s) AddEdgetoMST(V[v], v);
	if (D[v] == INFINITY) return; // Remaining vertices
	for (w = G->first(v); w<G->n(); w = G->next(v,w))
	if (D[w] > G->weight(v,w))
		{
    
    D[w] = G->weight(v,w);
		V[w] = v; temp.distance = D[w];
		temp.vertex = w;
		H.insert(temp); // Insert new distance in heap
		}
	}
}

Nota: Adecuado para gráficos densos.

2. Algoritmo de Kruskal

Idea del algoritmo: el algoritmo de Kruskal también es un cálculo simple y codicioso. Primero, divida el conjunto de vértices en clases de equivalencia | V |, y cada clase de equivalencia incluye un vértice. Luego, los bordes se procesan en orden del tamaño del peso. Si una arista conecta dos vértices de diferentes clases de equivalencia, esta arista se agrega al MST y las dos clases de equivalencia también se fusionan en una. Repita este proceso hasta que solo quede una clase de equivalencia.

Implementación de pseudocódigo:

Class KruskElem
{
    
    
Public:
	int from,to,distance;
	KruskElem()
	{
    
    from=to=distance=-1;}
	KreskElem(int f,int t,int d)
	{
    
    from=f;to=t;distance=d;}
};
Kruskel(Graph* G)
{
    
    
	Gentree A(G->n());
	KruskElem E[G->e()];
	int I;
	int edgecnt=0;
	for (i=0;i<G->n();i++)
	for (int w=G->first(I);w<G->weight(I,w))
	{
    
    E[edgecnt].distance=G->weight(i,w);
	E[edgecnt].from=i;
	E[edgecnt++].to=w;
	}
	Minheap<KruskElem,KKComp>H(E,edgecnt,edgecnt);
	int numMST=G->n();
	for (i=0;numMST>1;i++)
	{
    
    KruskElem temp;
	H.removemin(temp);
	int v=temp.from;
	int u=temp.to;
	if (A.differ(v,u))
		{
    
    A.UNION(v,u);
		AddEdgetoMST(temp.from,temp.to);
		numMST--;
		}
	}
}

Nota: se aplica a gráficos dispersos.

Supongo que te gusta

Origin blog.csdn.net/hyl1181/article/details/107783692
Recomendado
Clasificación