注解
1、并查集的应用。初始化、查找、合并、路径压缩。
2、关键是找到谁跟谁合并?此题应该是一个朋友圈中的人合并到一个集合中去。简单一点,把每个朋友圈的第一个人当作根节点,后面的人都跟他合并。
3、此题的输出还有一些技巧,因为要求按照输入的顺序,且不可重复。一个好的方法就是定义vector,用find方法(加入algorithm头文件)去重。
4、假如题目改成按id升序且不可重复输出,那么直接定义set是最方便的。
代码
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
const int MAX = 100001;
int father[MAX];
int isRoot[MAX];
void init() {
for(int i=0; i<MAX; i++) {
father[i] = i;
}
}
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;
}
}
int main() {
init();
int T;
scanf("%d", &T);
for(int i=0; i<T; i++) {
int m;
scanf("%d", &m);
int first;
scanf("%d", &first);
for(int i=1; i<m; i++) {
int b;
scanf("%d", &b);
Union(first, b);
}
}
memset(isRoot, 0, sizeof(isRoot));
for(int i=0; i<MAX; i++) {
isRoot[findFather(i)]++;
}
vector<int> vec;
scanf("%d", &T);
vector<int>::iterator result;
for(int i=0; i<T; i++) {
int num;
scanf("%d", &num);
if(isRoot[findFather(num)]==1) {
result = find(vec.begin( ), vec.end( ), num);
if(result == vec.end( )) {
vec.push_back(num);
}
}
}
if(vec.size()>0) {
for(int i=0; i<vec.size()-1; i++){
printf("%05d ", vec[i]);
}
printf("%05d\n", vec[vec.size()-1]);
} else {
printf("No one is handsome\n");
}
return 0;
}