http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4809
题意:
给出order数n
给出n行order<3种>
第一种:travel A m a1 .. ai .. an表示来了同学A 其中知道m个信息 信息号为a1 .. ai .. an..
第二种:share A B表示 A和B同学分享了她们共有的信息..其中信息可传递..并且和share先后无关..
第三种:check A 表示问A同学知道了多少条信息
思路:
用map<string, int> 来让同学名字变成序号..
share则使用并查集,对人名使用并查集。share时合并则使用set的插入,优化:让size小的插入size大的。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <algorithm>
#include<string>
using namespace std;
//const double eps=1e-7;
//const double INF=1e50;
//const double pi=acos(-1);
#define N 100005
#define M 1000005
int f[N],n,people;
char order[10],name1[20],ch,name2[20];
string na,nb;
map<string,int> a;
map<int,int> info;
set<int> b[N];
int root(int s)
{
if (f[s]==s) return s;
f[s]=root(f[s]);
return f[s];
/*int temp=s;
while(f[temp]!=temp)temp=f[temp];
while(f[s]!=s){s=f[s];f[s]=temp;}
return temp;*/
}
int main()
{
//freopen("a","r",stdin);
int i,m,j,k,in;
while (scanf("%d",&n)!=EOF)
{
a.clear();
for (i=0;i<n;i++) b[i].clear();
info.clear();
people=0;
in=0;
for (i=1;i<=n;i++)
{
gets(name1);
scanf("%s %s",order,name1);
na=name1;
if (order[0]=='a')
{
a[na]=people;
f[people]=people;
scanf(" %d",&m);
map<int,int>::iterator it;
int ss;
for (j=1;j<=m;j++)
{
scanf("%d",&k);
it=info.find(k);
if (it==info.end())
{
in++;
info[k]=in;//不要写反了
ss=in;
}
else ss=(*it).second;
b[people].insert(ss);
}
people+=1;
}
else if (order[0]=='s')
{
int n1,n2,n3;
scanf(" %s",name2);
nb=name2;
map<string,int>::iterator it;
it=a.find(na);
n1=(*it).second;
it=a.find(nb);
n2=(*it).second;
n1=root(n1);//找根不可缺少
n2=root(n2);
if (n1==n2) continue;
if (b[n1].size()<b[n2].size())
{
n3=n1;
n1=n2;
n2=n3;
}
set<int>::iterator it1;
for (it1=b[n2].begin();it1!=b[n2].end();it1++) b[n1].insert(*it1);
b[n2].clear();
f[n2]=n1;
}
else
{
int n1;
map<string,int>::iterator it;
it=a.find(na);
n1=(*it).second;
n1=root(n1);
printf("%d\n",b[n1].size());
}
}
}
return 0;
}