题目链接:http://acm.swust.edu.cn/problem/772/
Time limit(ms): 1000 Memory limit(kb): 65535
Description
每个人都有朋友,朋友也有很多种,比如:
石友--情谊坚贞的朋友。
挚友--志同道合的朋友。
益友--于己有帮助的朋友。
闺友--闺房中无话不谈的朋友。
君子交:指道义之交,即在道义上相互支持的朋友。
竹马之交:少年时骑竹马为戏的朋友,指自幼相交的朋友,等等。
现在dearway定义如果王二和张三是朋友,李四和张三也是朋友,那么王二和李四也是朋友,即朋友具有传递关系。现在给你N种朋友关系,问你有多种朋友集合,这些集合里不会出现两个朋友来自两个不同的集合。
Input
多组数据输入(小于等于10组)。每组数据第一行为一个整数N( 1 <= N <= 1000)表示N种朋友关系,接下来N行,每行首先输入一个整数ni( 1 <= ni <= 10)表示该种朋友关系中包含ni个人。然后ni个字符串,每个字符串由52个大小写英文字母及数字组成且长度小于10,表示ni个不同的人。
Output
每组数据输出一行,表示满足要求的答案。
Sample Input
4 2 Hilary Dearway 1 Hilary 2 Rusty Serena 2 Serena Luoxi 10 2 a b 2 b c 1 c 3 a d e 2 e f 2 f g 2 g h 2 h i 2 j k 1 z |
Sample Output
2 3 |
解题思路:一个并查集问题,每输入一个集合,朋友集合种类+1,然后并查集合并,看是否能合并到一个集合(种类-1),由于字符串不太好操作
利用map强大的字符处理能力,把字符串一一对应成数字进行操作,具体的看代码吧~~~
代码入下:
1 #include<iostream> 2 #include<map> 3 #include<string> 4 using namespace std; 5 #define maxn 10001 6 map<string, int>mpt; 7 int father[maxn], ans, n, cnt, num; 8 void init(){ 9 mpt.clear(); 10 cnt = ans = 0; 11 for (int i = 0; i < maxn; i++) 12 father[i] = i; 13 } 14 int findset(int x){ 15 return father[x] != x ? father[x] = findset(father[x]) : father[x]; 16 } 17 void mergy(int a, int b){ 18 int x = findset(a), y = findset(b); 19 if (x == y) return; 20 else{ 21 father[x] = y; 22 ans--; 23 } 24 } 25 int main(){ 26 string s; 27 while (cin >> n){ 28 init(); 29 for (int i = 1; i <= n; i++){ 30 int a, b; 31 cin >> num >> s; 32 if (!mpt[s]){ 33 a = ++cnt; 34 mpt[s] = cnt; 35 ans++; 36 } 37 else a = mpt[s]; 38 for (int j = 1; j < num; j++){ 39 cin >> s; 40 if (!mpt[s]){ 41 b = ++cnt; 42 mpt[s] = cnt; 43 ans++; 44 mergy(a, b); 45 } 46 else{ 47 b = mpt[s]; 48 mergy(a, b); 49 } 50 } 51 } 52 cout << ans << endl; 53 } 54 return 0; 55 }