Y busque plantillas optimizadas

1. La primera es encontrar la plantilla optimizada. Si los datos no son grandes, combínelos directamente de forma manual y podrá utilizar el método de búsqueda

int find(int x){
    while(x != p[x]){
		p[x] = p[p[x]];
		x = p[x];
	}
	return x;
}

Este método es adecuado para inicializar el valor p de cada nodo en sí mismo para evitar la explosión de la pila.

En segundo lugar, cuando hay más nodos y es necesario registrar el número de datos en cada colección, se utiliza la optimización del almacenamiento del número negativo del nodo raíz y cada vez que se fusiona en la rama más profunda del nodo.

void init(){
	for(int i = 1; i <= n;i++){
		p[i] = -1;
	}
}

int find(int x){        //数据打了会爆栈
	if(p[x] < 0)return x;
	else return p[x] = find(p[x]);
}

int find2(int x) {
	while(p[x] > 0 && p[p[x]] > 0){
		p[x] = p[p[x]];
		x = p[x];
	}
	return x;
}

void union_(int a, int b){
	int p1 = find(a);
	int p2 = find(b);
	if(p[p1] < p[p2]){ //合并,p1顶点更多(负数),因此合并到p2上,减少查找次数 
		p[p2] += p[p1];
        p[p1] = p2;
	}else{	//将p2合并到p1集合,减少查找次数。 
		p[p1] += p[p2];
		p[p2] = p1;
	}
}

Mientras ahorra espacio de esta manera, también puede elegir la búsqueda recursiva o la búsqueda circular, y find2 evita la explosión de la pila.
Cada nodo raíz se inicializa a -1, lo que significa que solo hay un nodo en este conjunto, que es él mismo. Si un nodo no es el nodo líder de este conjunto, entonces su valor p es positivo, que es su nodo líder.


Ejemplo de código de tiempo de espera:

#include<cstdio>
#include<cstring> 
#include<algorithm>
using namespace std;

int n, m;
int p[30005];
void init(){
	for(int i = 0; i <= n;i++){
		p[i] = -1;
	}
}

int find(int x) {
//	if(p[x] < 0)return x;
//	return p[x] = find(p[x]);
	int r = x;
    while(p[r] >= 0)	//以负数头下标为 记录节点数时,需要其前驱下标为0合法的情况,只有为负数才是头节点 
        r = p[r];
    int i = x, j;
    while(p[i] >= 0 && p[i] != r){
        j = p[i];
        p[i] = r;
        i = j;
    }
    return r;
}

void un(int a, int b){//合并 
	int p1 = find(a);
	int p2 = find(b);
	if(p[p1] < p[p2]){
		p[p2] += p[p1];
		p[p1] = p2;
	}else{
		p[p1] += p[p2];
		p[p2] = p1;
	}
}

int main(){
	int k, s, lid;
	while(scanf("%d%d",&n,&m), n || m){
		init();
		for(int i = 1; i <= m;i++){
			scanf("%d",&k);
			scanf("%d",&lid);
			for(int i = 1; i < k;i++){//少一个输入 
				scanf("%d", &s);
				un(s, lid);		//每一次输入都与第一个合并;最后直接找0的集合元素个数。
			}
		}
		int t = find(0);
		printf("%d\n", -p[t]);
	}
	
	return 0;
}

/*
100 4
2 1 2
5 10 13 11 12 14
2 0 1
2 99 2
*/

 

Supongo que te gusta

Origin blog.csdn.net/qq_40596572/article/details/103946279
Recomendado
Clasificación