浙大PTA

题目链接:https://pta.patest.cn/pta/test/1342/exam/4/question/21732

#include "iostream"
#include "algorithm"
using namespace std;
int father[10001], n;
/* 合并思路:
   1.要将小子树合并到大子树上 反过来合并 树会退化成单链表  导致查询时间变为线性时间 从而导致超时 
   2. 可以采用按节点数大小合并  也可以按树高进行归并(树高变化当且仅当进行归并的2个树高度相同) 
   3. 本题采用按节点数进行归并 
   4. 路径压缩 (防止测试数据总是从叶子节点查询 导致O(n*log(n))的查询时间复杂度) 
   */
void Init() { 
	for (int i = 1; i <= n; i++)
		father[i] = -1; /* 初始化为当前树的节点数的相反数 */  
}
int Find(int x) { /* 查询根节点  */
	if (father[x] <= -1)
		return x;
	else
		return father[x] = Find(father[x]); /* 路径压缩  */
}

void Union(int x, int y) {
	x = Find(x);
	y = Find(y);
	if(father[x] < father[y]){  /* 按节点数大小进行归并 */
		father[x] += father[y];
		father[y] = x;
		n--; /* 2个集合归并 总集合数减一*/
	}
	else {
		father[y] += father[x];
		father[x] = y;
		n--;
	}
}
int main() {
	char ch;
	int i, j;
	cin >> n;
	Init();
	bool flag = true;
	while (cin >> ch) {

		//cout << ch << endl;
		if (ch == 'S') {
			if (n == 1)
				cout << "The network is connected." << endl;
			else
				cout << "There are " << n << " components." << endl;
			break;
		}
		cin >> i >> j;
		switch (ch) {
		case 'C':
			if (Find(i) == Find(j)) {
				cout << "yes" << endl;
			}
			else {
				cout << "no" << endl;
			}
			break;
		case 'I':Union(i, j); break;
		}
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/minesweeper/p/5926717.html