UVA11987 并查集
2016-10-05 00:27
246 查看
第一、三个操作 直接带权并查集就可以解决关键是第二个
第二个问题在于合并两个节点的时候 第一个节点的子节点会跟着合并到第二个节点中 这提示我们 只要1~n都不作为父节点就可以了
所以初始化的时候将 每个节点的父亲节点设为 n+i 这样无论怎样合并节点1~n都不可能成为父节点 那么进行第二个操作的时候只要 将p节点合并到q节点父节点下就可以了
具体看代码 第一个操作和第二个操作合并时的区别
网上还有一种方法就是删边 滞空节点 建新节点 感觉没有这个方法简单好理解。
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=200010;
int pa[maxn],cnt[maxn];
ll sum[maxn];
int n,m;
void init()
{
for(int i = 1; i <= n; ++i) {
pa[i]=i+n;
cnt[i+n]=1;
sum[i+n]=i;
}
for(int i = 1; i <=n; ++i) {
pa[i+n]=i+n;
}
}
int findset(int x)
{
return x==pa[x]?x:pa[x]=findset(pa[x]);
}
int main()
{
// freopen("in.txt","r",stdin);
int t,p,q;
while(~scanf("%d%d",&n,&m)) {
init();
while(m--) {
scanf("%d",&t);
if(t==1) {
scanf("%d%d",&p,&q);
int x=findset(p),y=findset(q);
if(x!=y) {
pa[x]=y;
cnt[y]+=cnt[x];
sum[y]+=sum[x];
}
}
else if(t==2) {
scanf("%d%d",&p,&q);
int x=findset(p),y=findset(q);
if(x!=y) {
pa[p]=y;
cnt[x]--;
cnt[y]++;
sum[y]+=p;
sum[x]-=p;
}
}
else {
scanf("%d",&p);
int x=findset(p);
printf("%d %d\n",cnt[x],sum[x]);
}
}
}
return 0;
}
第二个问题在于合并两个节点的时候 第一个节点的子节点会跟着合并到第二个节点中 这提示我们 只要1~n都不作为父节点就可以了
所以初始化的时候将 每个节点的父亲节点设为 n+i 这样无论怎样合并节点1~n都不可能成为父节点 那么进行第二个操作的时候只要 将p节点合并到q节点父节点下就可以了
具体看代码 第一个操作和第二个操作合并时的区别
网上还有一种方法就是删边 滞空节点 建新节点 感觉没有这个方法简单好理解。
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=200010;
int pa[maxn],cnt[maxn];
ll sum[maxn];
int n,m;
void init()
{
for(int i = 1; i <= n; ++i) {
pa[i]=i+n;
cnt[i+n]=1;
sum[i+n]=i;
}
for(int i = 1; i <=n; ++i) {
pa[i+n]=i+n;
}
}
int findset(int x)
{
return x==pa[x]?x:pa[x]=findset(pa[x]);
}
int main()
{
// freopen("in.txt","r",stdin);
int t,p,q;
while(~scanf("%d%d",&n,&m)) {
init();
while(m--) {
scanf("%d",&t);
if(t==1) {
scanf("%d%d",&p,&q);
int x=findset(p),y=findset(q);
if(x!=y) {
pa[x]=y;
cnt[y]+=cnt[x];
sum[y]+=sum[x];
}
}
else if(t==2) {
scanf("%d%d",&p,&q);
int x=findset(p),y=findset(q);
if(x!=y) {
pa[p]=y;
cnt[x]--;
cnt[y]++;
sum[y]+=p;
sum[x]-=p;
}
}
else {
scanf("%d",&p);
int x=findset(p);
printf("%d %d\n",cnt[x],sum[x]);
}
}
}
return 0;
}
相关文章推荐
- 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 并查集(虚拟节点)
- UVA 11987 Almost Union-Find(并查集)
- uva 11987 删点并查集
- uva 11987 Almost Union-Find (并查集删点,转移)
- UVA 11987 第一次并查集
- 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(并查集)
- UVa-11987 Almost union-find(带删除操作的并查集)
- UVa 11987 并查集 Almost Union-Find