并查集带删除操作uva11987(好)
2014-02-27 15:54
183 查看
题意:初始有N个集合,分别为 1 ,2 ,3 .....n。有三种操件
1 p q 合并元素p和q的集合
2 p q 把p元素移到q集合中
3 p 输出p元素集合的个数及全部元素的和。
思路:并查集操作。1、3步比较容易实现,只要建立一个sum[],cnt[],记录每个结点相应值,和并时把值更新到根结点,输出时只要找到根结点输出其值即可。
但2操作有点麻烦,并查集没有删除操作。原先以为直接把p指向q的根就行了,但发现这是错的。如果p是叶子结点,那没问题,但如果是某个集合的根呢。我们只是要把这一个元素移掉,如果直接把p指向q的根,它的叶子结点也指向了。。。
换个思路,将p这个点对它所在的集合的“影响”将为0。然后再新开一个节点表示p这个节点就相当于把p从原来的集合中剥离出来了。因此相比原来的并查集,需要多一个id[p]数组表示点p现在的标号,原来的编号不变,如果p是根节点的话,相当于现在是原来集合的虚拟根节点。
1 p q 合并元素p和q的集合
2 p q 把p元素移到q集合中
3 p 输出p元素集合的个数及全部元素的和。
思路:并查集操作。1、3步比较容易实现,只要建立一个sum[],cnt[],记录每个结点相应值,和并时把值更新到根结点,输出时只要找到根结点输出其值即可。
但2操作有点麻烦,并查集没有删除操作。原先以为直接把p指向q的根就行了,但发现这是错的。如果p是叶子结点,那没问题,但如果是某个集合的根呢。我们只是要把这一个元素移掉,如果直接把p指向q的根,它的叶子结点也指向了。。。
换个思路,将p这个点对它所在的集合的“影响”将为0。然后再新开一个节点表示p这个节点就相当于把p从原来的集合中剥离出来了。因此相比原来的并查集,需要多一个id[p]数组表示点p现在的标号,原来的编号不变,如果p是根节点的话,相当于现在是原来集合的虚拟根节点。
#include<iostream> #include<cstdio> using namespace std; const int maxn=200010; int n,m,depth; int pra[maxn],id[maxn],num[maxn]; long long sum[maxn]; void init() { depth=n; for(int i=0;i<=n;i++) { pra[i]=id[i]=sum[i]=i; num[i]=1; } } int find(int x) { if(pra[x]==x)return x; return pra[x]=find(pra[x]); } void unite(int p,int q) { int x=find(p); int y=find(q); pra[x]=y; sum[y]+=sum[x]; num[y]+=num[x]; } void move(int p) { int x=find(id[p]); sum[x]-=p; num[x]--; id[p]=++depth;//新开一个节点 sum[id[p]]=p; num[id[p]]=1; pra[id[p]]=id[p]; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif int op,p,q; while(scanf("%d%d",&n,&m)!=EOF) { init(); for(int i=0;i<m;i++) { scanf("%d",&op); if(op==1) { scanf("%d%d",&p,&q); if(find(id[p])!=find(id[q])) unite(id[p],id[q]); } else if(op==2) { scanf("%d%d",&p,&q); if(find(id[p])!=find(id[q])) {move(p);unite(id[p],id[q]);} } else { scanf("%d",&p); int x=find(id[p]); printf("%d %lld\n",num[x],sum[x]); } } } return 0; }
相关文章推荐
- UVA11987_Almost Union-Find(并查集删除操作)
- uva11987(加权并查集的删除操作)
- HDU 2473 Junk-Mail Filter(并查集的删除操作)
- UVA11987:Almost Union-Find (并查集的删除)
- hdu 2473 Junk-Mail Filter(并查集的删除操作)
- uva 11987 Almost Union-Find(带删除操作的并查集)
- foj2155 - 盟国 (并查集的删除操作)
- UVA11987 带删除的并查集
- Hdu 2473(并查集删除操作) Junk-Mail Filter
- Hdu 2473(并查集删除操作) Junk-Mail Filter
- uva11987 - Almost Union-Find 并查集删除元素
- HDU 2473 Junk-Mail Filter (并查集的删除操作)
- NYOJ1022合纵连横(支持删除操作的并查集)
- hdu 2473 (并查集 删除操作)
- UVA 11987 Almost Union-Find(带有删除操作的并查集)
- HDU 2473 Junk-Mail Filter (并查集的删除操作)
- UVA 11987 Almost Union-Find(有删除操作的并查集)
- HDU 2473 Junk-Mail Filter 并查集,虚拟删除操作
- HDU 1473 并查集 删除结点操作 建立虚拟根结点
- 带权并查集--删除--UVA11987