A1107 Social Clusters (30分)

一、技术总结

  1. 这是一道并查集的题目,这里无非就是明白题目的含义,然后将套路用上基本上问题不大。
  2. 一个是father数组用于存储父亲结点,isRoot用于存储根结点,如果题目需要,还可以建立一个course数组,用于存储,例如这个题目就是用于判断该该兴趣是否有人涉及。
  3. findFather函数,用于查找结点的父亲结点,同时包含压缩路径。
  4. Union函数,用于合并。
  5. 初始化函数。

二、参考代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1010;
int father[maxn];
int isRoot[maxn] = {0};
int course[maxn] = {0};
int findFather(int x){
	int a = x;
	while(x != father[x]){
		x = father[x];
	}
	//路径压缩
	while(a != father[a]){
		int z = a;
		a = father[a];
		father[z] = x;
	} 
	return x;
}
void Union(int a, int b){
	int faA = findFather(a);
	int faB = findFather(b);
	if(faA != faB){
		father[faA] = faB;
	}
} 
void init(int n){
	for(int i = 1; i <= n; i++){
		father[i] = i;
		//isRoot[i] = false;
	}
}
bool cmp(int a, int b){//将isRoot数组从大到小排序  
	return a > b;
}
int main(){
	int n, k, h;
	scanf("%d", &n);
	init(n);
	for(int i = 1; i <= n; i++){
		scanf("%d:", &k);
		for(int j = 0; j < k; j++){
			scanf("%d", &h);
			if(course[h] == 0){
				course[h] = i;
			}
			Union(i, findFather(course[h]));
		}
	} 
	for(int i = 1; i <= n; i++){
		isRoot[findFather(i)]++;
	}
	int ans = 0;
	for(int i = 1; i <= n; i++){
		if(isRoot[i] != 0){
			ans++;
		}
	}
	printf("%d\n", ans);
	sort(isRoot+1, isRoot+n+1, cmp);
	for(int i = 1; i <= ans; i++){
		if(i != 1) printf(" ");
		printf("%d", isRoot[i]);
	}
	return 0;
}
posted @ 2020-02-23 15:42  睿晞  阅读(116)  评论(0编辑  收藏  举报