UVa 11987 Almost Union-Find(带权并查集)
2015-03-20 10:49
148 查看
本题难点就是第二个操作。如果可以保证移动的节点一定是叶子节点,那就可以直接修改fa数组了。
为了实现这点,可以开2×n个节点,初始时i的父节点是i+n,这样在合并时可以保证前n个节点一定一直都是叶子节点,问题就变成简单并查集了。
代码:
为了实现这点,可以开2×n个节点,初始时i的父节点是i+n,这样在合并时可以保证前n个节点一定一直都是叶子节点,问题就变成简单并查集了。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define maxn 200005 int fa[maxn]; int num[maxn]; int sum[maxn]; int N,M; void init(){ for(int i=1;i<=N;i++){ fa[i]=i+N; sum[i]=i; num[i]=1; } for(int i=N+1;i<=2*N;i++){ fa[i]=i; sum[i]=i-N; num[i]=1; } } int Find(int n){ if(n!=fa ) return fa =Find(fa ); return fa ; } void Union(int x,int y){ if(Find(x)==Find(y)) return; int tx=Find(x),ty=Find(y); fa[tx]=ty; num[ty]+=num[tx]; sum[ty]+=sum[tx]; } void Move(int x,int y){ int tx=Find(x),ty=Find(y); num[tx]--; sum[tx]-=x; num[ty]++; sum[ty]+=x; fa[x]=ty; } void Show(int x){ int tx=Find(x); printf("%d %d\n",num[tx],sum[tx]); } int main(){ while(~scanf("%d%d",&N,&M)){ init(); for(int i=0;i<M;i++){ int k; scanf("%d",&k); int x,y; if(k==1){ scanf("%d%d",&x,&y); Union(x,y); } else if(k==2){ scanf("%d%d",&x,&y); Move(x,y); } else { scanf("%d",&x); Show(x); } } } return 0; } /* 3 6 1 1 2 2 2 3 3 2 3 3 3 1 */
相关文章推荐
- UVA 11987 Almost Union-Find(并查集)
- UVA - 11987 Almost Union-Find (并查集)
- UVA11987 - Almost Union-Find (并查集带删除)
- UVA 11987 Almost Union-Find(有删除操作的并查集)
- UVA 11987 Almost Union-Find(并查集的删除)
- UVA 11987 Almost Union-Find(并查集)
- UVa 11987,Almost Union-Find,并查集
- UVA 11987 Almost Union-Find(带删除的并查集)
- UVA 11987 Almost Union-Find 并查集单点修改
- UVA 11987 - Almost Union-Find(并查集)
- UVA - 11987 Almost Union-Find(带删除的并查集)
- UVA 11987 Almost Union-Find 并查集节点删除
- UVA 11987 - Almost Union-Find(并查集)
- UVa 11987 并查集 Almost Union-Find
- uva 11987 Almost Union-Find (并查集)
- uva 11987 Almost Union-Find(带删除操作的并查集)
- uva11987 Almost Union-Find(可删除元素的并查集)
- UVA 11987 - Almost Union-Find 并查集的活用 id化查找
- UVa 11987 Almost Union-Find(支持删除操作的并查集)
- UVA - 11987 Almost Union-Find(带删除的并查集)