这里学习了一下别人的代码。第一次做并查集。跳了进度,学校集训队要找人了。时间紧迫啊。下面还要线段树
下面是代码
#include <map>
#include <set>
#include <list>
#include <cmath>
#include<cctype>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b)
{
return a % b == 0 ? b : gcd(b, a % b);
}
int parent[100010];
int n,m;
int size[100010];
long long sum[100010];
int pos[100010];
inline void init()//注意这里忽略下标0
{
for (int i=1;i<=n;i++)
{
sum[i]=pos[i]=parent[i]=i;
size[i]=1;
}
}
inline int find(int x)
{
return parent[x]==x?x:find(parent[x]);
}
int main()
{
while (scanf("%d%d",&n,&m)==2)
{
init();
int cond,p,q;
for (int i=0;i<m;i++)
{
scanf("%d",&cond);
if (cond==1)
{
//合并,把q所在的集合合并到p
scanf("%d%d",&p,&q);
int x=find(pos[p]);
int y=find(pos[q]);
if (x==y) continue;
sum[x]+=sum[y];
size[x]+=size[y];
parent[y]=x;
}
if (cond==2)
{
scanf("%d%d",&p,&q);
int x=find(pos[p]);
int y=find(pos[q]);
if (x==y) continue;
//把p插入q所在的集合,并再p所在的集合中删除p(p移动到q所在的集合中
sum[x]-=p;
size[x]--;
sum[y]+=p;
size[y]++;
pos[p]=++n;//模拟删除操作
sum[pos[p]]=p;
size[pos[p]]=1;
parent[pos[p]]=y;
}
if (cond==3)
{
scanf("%d",&p);
printf("%d %lld\n",size[find(pos[p])],sum[find(pos[p])]);
}
}
}
return 0;
}