PTA File Transfer --- Collection operation

This is a question similar to the operation of the set

Ideas

  1. The logical structure of the set can be seen as a tree (the logical structure is shown in the figure below), and the representative element of each set is the root of the tree. When merging the sets corresponding to two elements, we need to know which set the write element corresponds to. , That is, find the representative elements corresponding to these sets (ie the root of the tree), and then perform operations such as merging
  2. This tree is the child node pointing to the parent node (the elements in the collection store the subscript of the representative element of the collection)
    .Insert picture description here
  3. We build the set into an array , because each node in the title is a continuous number, so it can be mapped to the number of each node through the subscript of the array , so the value stored in this array is the set corresponding to this node The subscript of the representative element, and when a node is a representative element, the negative number of the total number of elements in the set is stored (the negative number is to identify it as the representative element of the set, and the number of set elements is saved for Merge by rank)
  4. We regard the connection operation in the title as the concept of connecting two sets. Every time we want to connect the sets corresponding to two elements, we first Find the representative elements of the corresponding sets of these two elements, and compare the scale of the representative elements (each The number of elements contained in the set), the small scale is added to the large scale combination ( the tree corresponding to the small scale is added to the large scale tree )
  5. The Find function implements path compression . When you want to find the representative element of a certain element corresponding to the set, recursively from this node to the tree root, after finding the tree root, return the subscript of the tree root step by step (let the recursive elements directly Point to the root of the tree, making it more convenient to check the writing element next time)
#include <stdio.h>
#include <stdlib.h>

int Find(int S[], int X) {
    
    
	if (S[X] < 0) {
    
    
		return X;
	}
	else
		return S[X] = Find(S, S[X]); //路径压缩
}

//按秩归并
void Union(int S[], int root1, int root2) {
    
     //比规模进行
	if (S[root2] < S[root1]) {
    
    
		S[root2] += S[root1];
		S[root1] = root2;
	}
	else {
    
    
		S[root1] += S[root2];
		S[root2] = root1;
	}
}

void Input_connection(int S[]) {
    
    
	int u, v;
	int root1, root2;
	scanf("%d %d\n", &u, &v);
	root1 = Find(S, u - 1);
	root2 = Find(S, v - 1);  //v这个元素在数组中下标为v-1的地方
	if (root1 != root2)
		Union(S, root1, root2);
}

void Check_connection(int S[]) {
    
    
	int u, v;
	int root1, root2;
	scanf("%d %d\n", &u, &v);
	root1 = Find(S, u - 1);
	root2 = Find(S, v - 1);  //v这个元素在数组中下标为v-1的地方
	if (root1 == root2)
		printf("yes\n");
	else
		printf("no\n");
}

void Check_network(int S[], int n) {
    
    
	int i, counter = 0;
	for (i = 0; i < n; i++) {
    
    
		if (S[i] < 0)
			counter++;
	}
	if (counter == 1)
		printf("The network is connected.\n");
	else
		printf("There are %d components.\n", counter);
}

void Init(int S[], int n) {
    
    
	for (int i = 0; i < n; i++) {
    
    
		S[i] = -1;
	}
}

int main() {
    
    
	int S[10000]; //对于结点-1的为在数组中下标,而其中的值为父结点的下标,父结点的值为集合元素的个数的负值
	int n;
	char in;
	scanf("%d\n", &n);
	Init(S, n);
	do {
    
    
		scanf("%c", &in);
		switch (in) {
    
    
			case'I':Input_connection(S); break;
			case'C':Check_connection(S); break;
			case'S':Check_network(S, n); break;
		}
	} while (in != 'S');
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_43779658/article/details/105173999