题目链接:ZOJ 3641 Information Sharing
并查集 + set + map。
这题难点在合并两个kid,还得把两个kid携带的几个信息合并,当然重复的不算,这很显然得用set,set的insert方法不插入重复元素。
kid的区别体现在名字上,这个名字是个字符串,而并查集使用int型搞的,那么应该能想起键值对,就是map。
还有一个要注意的是合并kid携带信息时候要把小的合并到大的,要不然就内存就超了。或者合并一个以后就把没用的clear了。结合起来更好。
#include <iostream>
#include <map>
#include <set>
#include <iterator>
using namespace std;
const int MAX_N = 100000 + 100;
map<string,int> _map;
set<int> _set[MAX_N];
int p[MAX_N];
int n;
int _find(int i)
{
return p[i] == i ? i : (p[i] = _find(p[i]));
}
int main()
{
char flag[10],name[20],name1[20],name2[20];
int _count,a,b,u,v,num,temp;
set<int>::iterator iter;
while(cin >> n)
{
_count = 0;
_map.clear();
for(int i = 0;i < n;i++)
_set[i].clear();
for(int i = 0;i < n;i++)
p[i] = i;
for(int i = 0;i < n;i++)
{
cin >> flag;
if(flag[0] == 'a')
{
string name;
cin >> name;
_map[name] = _count;
cin >> num;
for(int j = 0;j < num;j++)
{
cin >> temp;
_set[_count].insert(temp);
}
_count++;
}
else if(flag[0] == 's')
{
cin >> name1 >> name2;
a = _map[name1];
b = _map[name2];
u = _find(a);
v = _find(b);
if(u == v)
continue;
if(_set[u].size() < _set[v].size())
p[u] = v;
else
{
p[v] = u;
temp = u;
u = v;
v = temp;
}
for(iter = _set[u].begin();iter != _set[u].end();iter++)
_set[v].insert(*iter);
_set[u].clear();
}
else if(flag[0] == 'c')
{
cin >> name;
a = _map[name];
u = _find(a);
cout << _set[u].size() << endl;
}
}
}
return 0;
}