题目描述大致如下:
给定n个关系,每次给出关系的时候,求出这个集合的中人的总数,每次合并这两个人所在的集合
因为每次给出关系的时候都需要求出总数,所以每次去合并的时候去重新更新根节点,再去统计是不现实的.一开始因为这个TLE好几次.
之后发现其实每个子节点的个数也是可以合并到根节点去的,就类似p数组,可以定义sum数组,每次合并的时候,把子节点中的个数加入到父节点中,每次输出父节点的sum即可
还是费了一些时间,算是一个很不错的变形吧
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f3f
string a,b;
map<string ,int>m;
int cnt,t,n;
int p[100005];
long long sum[100005];
void init()
{
for(int i=0; i<100005; i++){
p[i]=i;
sum[i]=1;
}
cnt=0;
m.clear();
}
int find(int x)
{
return p[x]==x?x:p[x]=find(p[x]);
}
void merge(int a,int b)
{
int pa = find(a),pb= find(b);
//cout<<pa<<"!!"<<pb<<endl;
//cout<<sum[pa]<<"!!!!!"<<sum[pb]<<endl;
if(pa!=pb){
p[pb]=pa;
sum[pa]+=sum[pb];
}
}
int getans(int x){
int pa = find(x);
//cout<<x<<" "<<pa<<endl;
return sum[pa];
}
int main()
{
//freopen("1.txt","r",stdin);
std::ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
init();
cin>>n;
for(int i=0; i<n; i++)
{
cin>>a>>b;
if(m.count(a)==0)
m[a]=cnt++;
if(m.count(b)==0)
m[b]=cnt++;
merge(m[a],m[b]);
cout<<getans(m[b])<<endl;
}
}
return 0;
}