[PAT] A1107 Social Clusters

并查集

AC代码

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <cstdio>
#include <vector>
#include<algorithm>
using namespace std;
#define N 1002
int isRoot[N] = { 0 }, father[N];
vector<int>hobbies[N];
int findFather(int v) {
	int a = v;
	while (father[v] != v)v = father[v];
	while (father[a] != v) {
		int z = father[a];
		father[a] = v;
		a = z;
	}
	return v;
}
void merge(int a, int b) {
	int u = findFather(a);
	int v = findFather(b);
	if (u != v)father[u] = v;
}
bool ifmerge(int a, int b) {
	int flag = false;
	for (int i = 0;i < hobbies[a].size();i++)
		for (int j = 0;j < hobbies[b].size();j++) {
			if (hobbies[a][i] == hobbies[b][j])flag = true;
		}
	return flag;
}
bool cmp(int a, int b) {
	return a > b;
}
int main() { 
	int n, i, j;    
	scanf("%d", &n); 
	int thobby, numhobby;
	for (i = 1;i <= n;i++) {
		scanf("%d: ", &numhobby);
		for (j = 0;j < numhobby;j++) {
			scanf("%d", &thobby);
			hobbies[i].push_back(thobby);
		}
	}
	for (i = 1;i <= n;i++)
		father[i] = i;
	for (i = 1;i < n;i++) {
		for (j = i + 1;j <= n;j++) {
			if(ifmerge(i, j))
				merge(i, j);
		}
	}
	for (i = 1;i <= n;i++)
		isRoot[findFather(i)]++;
	int numcluster = 0;
	for (i = 1;i <= n;i++)
		if (isRoot[i] != 0)numcluster++;
	printf("%d\n", numcluster);
	sort(isRoot, isRoot + n + 1, cmp);
	if (isRoot[0] != 0)printf("%d", isRoot[0]);
	i = 1;
	while (isRoot[i] != 0) {
		printf(" %d", isRoot[i]);
		i++;
	}
	return 0; 
}

对比柳神的代码,发现爱好不需要用vector数组存起来,可以输入一个处理一个。即:

用course[t]表示任意一个喜欢t活动的人的编号。

  1. 如果当前的活动t之前没有人喜欢过(course[t]==0),那么就course[t] = i,i为它自己的编号,表示i为喜欢course[t]的一个人的编号。
  2. 如果t之前有人喜欢过了,那么就让i和喜欢这个活动的人(即course[t])处在同一个社交圈里, 即Union(i, findFather(course[t]))。

代码实现如下:

for(int i = 1; i <= n; i++) {
    scanf("%d:", &k);
    for(int j = 0; j < k; j++) {
        scanf("%d", &t);
        if(course[t] == 0)
            course[t] = i;
        else Union(i, course[t]);
    }
}
posted @ 2020-07-16 13:14  \0.0/  阅读(91)  评论(0编辑  收藏  举报