Almost Union-Find UVA - 11987(并查集的删除操作)
題意:求出每個集合的元素個數,及總和,給出三個操作:
1 將含有a元素和b元素的集合合并;2 將a元素放入含有b元素的集合中;3 輸出a元素所在集合的元素個數及總和;
思路:正常并查集,與并查集元素的刪除
題目:
I hope you know the beautiful Union-Find structure. In this problem, you’re to implement something similar, but not identical. The data structure you need to write is also a collection of disjoint sets, supporting 3 operati
| 1 p q | Union the sets containing p and q. If p and q are already in the same set, ignore this command. | 
| 2 p q | Move p to the set containing q. If p and q are already in the same set, ignore this command. | 
| 3 p | Return the number of elements and the sum of elements in the set containing p | 
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}
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<cstdlib> #include<cstring> #include<cstdio> #include<queue> #define Lint long long int using namespace std; const int MAXN=200010; int f[MAXN];/*盒子內的元素鏈接*/ int sum[MAXN];/*集合內元素之和*/ int p[MAXN];/*盒子*/ int siz[MAXN];/*集合內元素個數,下標為盒子下標*/ int n,m,cnt; int find(int x) {return x==f[x] ? f[x] : f[x]=find( f[x] ) ; } int main() {int opt,u,v,x,y;while( scanf("%d%d",&n,&m)!=EOF )//刪除節點,就是把原先的節點設置為虛點,然后把點的位置用num數組指向新的位置。{cnt=n;for(int i=1; i<=n; i++) f[i]=p[i]=sum[i]=i,siz[i]=1;for(int i=1; i<=m; i++){scanf("%d",&opt);if( opt==1 ){scanf("%d%d",&u,&v);u=p[u],v=p[v];u=find( u ),v=find( v );if( u==v ) continue ;f[u]=v;siz[v]+=siz[u],sum[v]+=sum[u];}if( opt==2 ){scanf("%d%d",&u,&v);x=find( p[u] ),y=find( p[v] );if( x==y ) continue ;sum[x]-=u,siz[x]--;/*盒子的名稱不變,除去該元素*/x=p[u]=++cnt;/*重新申請一個內存,里面只有要操作的元素,改變該元素的祖先*/f[x]=y;sum[y]+=u,siz[y]++;}if( opt==3 ){scanf("%d",&u);u=find( p[u] );printf("%d %d\n",siz[u],sum[u]);}}}return 0; }?
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Almost Union-Find UVA - 11987(并查集的删除操作)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 在linux下安装QQ游戏大厅linux
- 下一篇: 我的RGB外设推荐RGB外设
