1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include<iostream>
#include<map>
using namespace std;
map<string, string> leader;

/***
*并查集:
*如果要判断两个人是否属于一个朋友圈,只需要判断他们的leader是否为同一个人,这是一个查询的过程.
*如果两个人是好友关系,则需要把两个人并入同一个朋友圈,这是一个合并的过程.
*
*/
//每一行表示朋友关系
string input[] = {
"周芷若","张无忌",
"张无忌","韩小昭",
"成昆","陈友谅",
"杨逍","纪晓芙",
};

//测试每行的两人是否为朋友
string test[] = {
"周芷若","韩小昭",
"张无忌","成昆",
};

//初始化
void setLeader() {
int i = 1;
int totalPerson = 8;
for (i = 0;i < totalPerson; i++) {
leader[input[i]] = input[i]; //将自己初始化为自己的领导
}
}

//查找领导,看看究竟是谁
string findLeader(string s) {
string r = s;
while (leader[r] != r) {
r = leader[r];//没找到的话,一直往上找
}
return r;
}

//将两个领导的朋友圈合并,从此 leaderX和leaderY是同一个朋友圈了
void uniteSet(string leaderX, string leaderY) {
leader[leaderX] = leaderY;
}

int main() {
int numberOfSets = 7; //最开始有7个不重复的人
//初始化领导
setLeader();

int i = 0;
int j = 0;
int n = 4; //人物关系的数组有4行
for (j = 0;j < n;j++) {
string u = input[i++];
string v = input[i++];

//找领导
u = findLeader(u);
v = findLeader(v);

//领导不想等,则合并两个朋友圈
if (u != v) {
uniteSet(u, v);
numberOfSets--;
}
}
i = 0;
n = 2; //待测试人物关系的数组有2行
for (j = 0;j < n;j++) {
string u = test[i++];
string v = test[i++];

//找领导
u = findLeader(u);
v = findLeader(v);

//如果领导不同,则不属于同一个朋友圈
if (u != v) {
cout << "NO" << endl;
}
else { //如果两个领导相同,则肯定属于同一个朋友圈
cout << "YES" << endl;
}
}
cout << numberOfSets << endl;
return 0;
}