用并查集做
开一个map把字符串映射成标号。
用set表示每个人拥有的信息,在做并查集UNION操作时合并把一个人的祖先所拥有的信息合并到另一个人的祖先中。
set有自动去重功能,所以不用手动去重。
注意合并完后被合并的那个人的set要clear(),不然要mle
最后输出信息数时找祖先时脑残的写成了fa[n],而不是Find(n),wa了一次。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <string>
#include <set>
#define maxn 100010
using namespace std;
map <string,int> Hash;
set <int > G[100010];
int fa[maxn];
int Find(int n){
if(n==fa[n]) return n;
return fa[n]=Find(fa[n]);
}
void SetUnion(int t1,int t2){
set <int> :: iterator p;
for(p=G[t1].begin();p!=G[t1].end();p++){
int tmp=*p;
//if(G[t2].find(tmp)==G[t2].end()){
G[t2].insert(tmp);
//}
}
G[t1].clear();
}
int Union(int a,int b){
int t1=Find(a);
int t2=Find(b);
if(t1!=t2){
fa[t1]=t2;
SetUnion(t1,t2);
}
}
void init(int n){
for(int i=0;i<=n;i++){
G[i].clear();
fa[i]=i;
}
Hash.clear();
}
int main(){
int n;
while(~scanf("%d",&n)){
init(n);
int num=0;
while(n--){
char t[20];
scanf("%s",t);
if(t[0]=='a'){
string name;
cin>>name;
Hash[name]=++num;
int k;
scanf("%d",&k);
while(k--){
int id;
scanf("%d",&id);
G[num].insert(id);
}
}
else if(t[0]=='s'){
string a, b;
cin>>a>>b;
Union(Hash[a],Hash[b]);
}
else {
string a;
cin>>a;
int res=Find(Hash[a]);
printf("%d\n",G[res].size());
}
}
}
return 0;
}