本来觉得挺难的,特别是第二种操作,把p移到q的集合,看别人的代码就是p是根的时候怎样怎样,不是根的时候怎样怎样,看不懂~~
但是仔细一想,如果把第i个节点的根变为i+100000就什么都解决了~~~~
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define mxn 210000
#define ym 100200
#define inf 0x3f3f3f3f
#define eps 1e-8
#define LL long long
#define ULL unsigned long long
#define MP make_pair
int fa[mxn], cnt[mxn];
LL sum[mxn];
int n, m;
int find( int x ) {
if( fa[x] != x )
fa[x] = find( fa[x] );
return fa[x];
}
void init() {
memset( sum, 0, sizeof( sum ) );
for( int i = 1; i <= n; ++i )
fa[i] = i + ym, fa[i+ym] = i + ym, sum[i+ym] = i, cnt[i+ym] = 1;
}
int main() {
while( scanf( "%d%d", &n, &m ) != EOF ) {
init();
int type, p, q;
for( int i = 1; i <= m; ++i ) {
scanf( "%d", &type );
scanf( "%d", &p );
if( type == 1 ) {
scanf( "%d", &q );
int u = find( p );
int v = find( q );
if( v == u )
continue;
fa[v] = u;
sum[u] += sum[v];
cnt[u] += cnt[v];
}
if( type == 2 ) {
scanf( "%d", &q );
int u = find( p );
int v = find( q );
fa[p] = v;
cnt[u]--;
sum[u] -= p;
sum[v] += p;
cnt[v] ++;
}
if( type == 3 ) {
int u = find( p );
printf( "%d %lld\n", cnt[u], sum[u] );
}
}
}
return 0;
}