zoj 3641 Information Sharing(set+并查集)

用并查集做

开一个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;
}



你可能感兴趣的:(并查集)