Initially, the collection contains n sets: {1}, {2}, {3}, … , {n}.
Input
There are several test cases. Each test case begins with a line containing two integers n and m
(1 ≤ n, m ≤ 100, 000), the number of integers, and the number of commands. Each of the next m lines
contains a command. For every operation, 1 ≤ p, q ≤ n. The input is terminated by end-of-file (EOF).
Output
For each type-3 command, output 2 integers: the number of elements and the sum of elements.
Explanation
Initially: {1}, {2}, {3}, {4}, {5}
Collection after operation 1 1 2: {1,2}, {3}, {4}, {5}
Collection after operation 2 3 4: {1,2}, {3,4}, {5} (we omit the empty set that is produced when
taking out 3 from {3})
Collection after operation 1 3 5: {1,2}, {3,4,5}
Collection after operation 2 4 1: {1,2,4}, {3,5}
输入 1 a b 把a,b所在的集合合并
输入 2 a b 把b从b所在的旧集合移到a的集合中
输入 3 a 输出a所在集合的元素个数和这个集合的元素和
一开始想并查集能做吗 怎么这么像stl 最后发现还是并查集
思路,如何删除一个并查集里面的一个元素加到另一个并查集内,通过思考发现,旧的并查集如果移除的是一般的结点还好做,如果是根节点,出现群龙无首的情况是不行的,所以旧的集合里面的根节点 f[根节点]是不能改变的。那么改变什么才好,- -答案就是用一个新的数组 po 反应的是当前元素的根节点的最新位置,即移除后的位置。 所有的find和merge都用id数组来寻找根结点,而f永远指向的是根节点,那么删除的话虽然元素和减少了但是对根节点的指向是不会变化的 因为f[ ]没变,再用po创建一个大于n的新空间放这个单独的元素就好。
由于求的东西比较多,指向当前位置的用 数组po 指定的是最新的位置。
用sum数组求根的里存放的和来代表集合的和
用pre数组代表集合里面的个数。
用f求的是父节点和根 每一个集合,即使删除也有旧的集合保留。父节点依旧保留
#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
using namespace std;
const int maxn=100100;
int f[maxn];
int sum[maxn];
int pre[maxn];
int po[maxn];
int n,m;
int find(int x)
{
return (x==f[x])?f[x]:f[x]=find(f[x]);
}
int init()
{
for(int i=1;i<=n;i++)
{
f[i]=i;
sum[i]=i;
po[i]=i;
pre[i]=1;
}
}
void merge(int a,int b)
{
int p=find(a);
int q=find(b);
if(p!=q)
{
f[p]=q;
pre[q]+=pre[p];
sum[q]+=sum[p];
}
}
int main()
{
while(cin>>n>>m)
{
init();
int yi=n;
for(int i=0;i<m;i++)
{
int op;
cin>>op;
if(op==1)
{
int a,b;
cin>>a>>b;
merge(po[a],po[b]);
}
if(op==2)
{
int a,b;
cin>>a>>b;
int p1=find(po[a]);
int p2=find(po[b]);
if(p1!=p2)
{
int t=find(po[a]);
sum[t]-=a;
pre[t]--;
po[a]=++yi;
f[yi]=yi;
pre[yi]=1;
sum[yi]=a;
merge(po[a],po[b]);
}
}
if(op==3)
{
int a;
cin>>a;
int p1=find(po[a]);
cout<<pre[p1]<<" "<<sum[p1]<<endl;
}
}
}
}