11987 Almost Union-Find (並查集的節點刪除)
阿新 • • 發佈:2019-01-24
連線:
題意:
給你n個數 有m個操作,如果op==1 將x和y併到一個集合中去,如果op==2 如果x和y不在一個集合中,就將x從原集合中取出來放到y的集合中去,如果op==3 輸出x所在的集合的
元素的個數以及集合中元素的和。
思路 : 並查集的刪除操作,這裡我們定義一個id陣列,在刪除操作中我們那個沒有真正的刪除,而是改變了id陣列。這裡再開一個sum和num陣列分別表示集合中的元素的和 和元素的個數。
程式碼:
這裡還有一種 寫法,但是是超時的,雖說過不去,但是對於理解id陣列還是有一定的幫助,基本思路是一樣的。#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #define N 100005 using namespace std; long long sum[N]; int f[N],id[N],num[N]; int n,m; void init() { int i; for(i=1;i<=n;i++) { sum[i]=(long long)i; num[i]=1; f[i]=id[i]=i; } return ; } int getf(int x) { return f[x]==x?x:(f[x]=getf(f[x])); } void merge(int x,int y) { int t1=getf(id[x]); int t2=getf(id[y]); if(t1!=t2){ f[t2]=t1; sum[t1]+=sum[t2]; num[t1]+=num[t2]; } return ; } void del(int x) { int fa=getf(id[x]); num[fa]--; sum[fa]-=(long long)x; id[x]=++n; num[id[x]]=1; sum[id[x]]=(long long)x; f[id[x]]=id[x]; } int main() { int i,j,x,y,op; while(scanf("%d %d",&n,&m)!=EOF) { init(); while(m--) { scanf("%d",&op); if(op==1) { scanf("%d %d",&x,&y); merge(x,y); } else if(op==2) { scanf("%d %d",&x,&y); int t1=getf(id[x]); int t2=getf(id[y]); if(t1!=t2){ del(x); merge(x,y); } } else{ scanf("%d",&x); int fa=getf(id[x]); printf("%d %lld\n",num[fa],sum[fa]); } /* printf("sum: "); for(i=1;i<=n;i++) printf("%lld ",sum[i]); printf("\nnum: "); for(i=1;i<=n;i++) printf("%d ",num[i]); printf("\n");*/ } } return 0; }
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #define N 100005 using namespace std; int f[N*3]; int n,m,id; void init() { int i; for(i=1;i<=n;i++) f[i]=i+n; for(i=n+1;i<=n+n+m;i++) f[i]=i; return ; } int getf(int x) { return f[x]==x?x:(f[x]=getf(f[x])); } void merge(int x,int y) { int t1=getf(x); int t2=getf(y); if(t1!=t2) { f[t2]=t1; } return ; } void del(int x) { f[x]=id++; } int main() { int i,j,op,x,y; while(scanf("%d %d",&n,&m)!=EOF) { init(); id=2*n+1; while(m--) { scanf("%d",&op); if(op==1){ scanf("%d %d",&x,&y); merge(x,y); } else if(op==2){ scanf("%d %d",&x,&y); int t1=getf(x); int t2=getf(y); if(t1==t2) continue; del(x); merge(x,y); } else if(op==3) { scanf("%d",&x); int fin; long long cnt=0; fin=0; int fa=getf(x); for(i=1;i<=n;i++) { if(getf(i)==fa){ fin++; cnt+=(long long)i; } } printf("%d %I64d\n",fin,cnt); } /* printf("fa: "); for(i=1;i<=n;i++) printf("%d ",getf(i)); printf("\n");*/ } } return 0; }