1~n,n个数,初始每个数独自作为一个集合,然后进行m次操作。
操作有三种:
1 p q :把 p 所在的集合合并到 q 所在的集合
2 p q :把 p 从 p 的集合中拿出,放到 q 的集合里
3 p :输出 p 所在的集合的元素个数和元素之和
Sample Input
5 7
1 1 2
2 3 4
1 3 5
3 4
2 4 1
3 4
3 3
Sample Output
3 12
3 7
2 8
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <map> #include <set> #include <stack> #include <vector> #define Twhile() int T;scanf("%d",&T);while(T--) #define clc(a,b) memset(a,b,sizeof(a)) #define fora(i,a,b) for(i=a;i<b;i++) #define fors(i,a,b) for(i=a;i>b;i--) #define fora2(i,a,b) for(i=a;i<=b;i++) #define fors2(i,a,b) for(i=a;i>=b;i--) #define PI acos(-1.0) #define eps 1e-6 #define INF 0x3f3f3f3f typedef long long LL; typedef long long LD; using namespace std; const int maxn= 100000+11; map<int,int>ma; int cou[maxn],sum[maxn]; int fa[maxn]; int n,m; void init() { ma.clear(); int i; fora2(i,1,n) { fa[i]=i;//第i个点的父亲是i cou[i]=1;//第i个集合个数为1 sum[i]=i;//第i个集合总和为i ma[i]=i;//第i个点属于第i个集合 } } int findx(int x) { if(x==fa[x])return x; return fa[x]=findx(fa[x]); } int main() { int kcase=0; while(~scanf("%d%d",&n,&m)) { init(); while(m--) { int op; scanf("%d",&op); if(op==3) //输出 p 所在的集合的元素个数和元素之和 { int x; scanf("%d",&x); int fx=findx(ma[x]); printf("%d %d ",cou[fx],sum[fx]); continue; } int x,y; scanf("%d%d",&x,&y); int fx=findx(ma[x]),fy=findx(ma[y]); if(fx==fy)continue; if(op==1) //1 p q :把 p 所在的集合合并到 q 所在的集合 { //合并连通分支fx和fy fa[fx]=fy; cou[fy]+=cou[fx]; sum[fy]+=sum[fx]; //清空fx cou[fx]=0; sum[fx]=0; continue; } //把x从集合ma[x]拿出来 //2 p q :把 p 从 p 的集合中拿出,放到 q 的集合里 sum[fx]-=x; cou[fx]--; //把x放到集合ma[y] ma[x]=ma[y]; cou[fy]++; sum[fy]+=x; } } return 0; }