您的位置:首页 > 其它

uva 11987 带删除操作的并查集与并查集的可持久化

2015-08-23 16:50 429 查看
难点在于操作2,对于叶子结点而言,删除是很简单的,而对于根节点,删除好像是“不可能的”,所以我们可以在初始化的时候动一些脑筋,让每个结点最开始的父亲不是自己而是一个”虚节点(i+n)“,这样所有的结点都变成了叶子结点,然后问题就变得容易解决了。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

typedef long long ll;
const int N = 200001;
int f
;
ll sum
;
int num
;
int n, m;

void init()
{
for ( int i = 1; i <= n; i++ )
{
f[i] = i + n;
}
for ( int i = n + 1; i <= 2 * n; i++ )
{
f[i] = i;
sum[i] = i - n;
num[i] = 1;
}
}

int findf( int x )
{
if ( f[x] != x ) f[x] = findf( f[x] );
return f[x];
}

void union_set( int x, int y )
{
x = findf(x), y = findf(y);
if ( x != y )
{
f[x] = y;
sum[y] += sum[x];
num[y] += num[x];
}
}

void move( int x, int y )
{
int fx = findf(x), fy = findf(y);
sum[fx] -= x;
num[fx]--;
f[x] = fy;
sum[fy] += x;
num[fy]++;
}

int main ()
{
while ( scanf("%d%d", &n, &m) != EOF )
{
init();
while ( m-- )
{
int op, p, q;
scanf("%d", &op);
if ( op == 1 )
{
scanf("%d%d", &p, &q);
union_set( p, q );
}
else if ( op == 2 )
{
scanf("%d%d", &p, &q);
move( p, q );
}
else
{
scanf("%d", &p);
p = findf(p);
printf("%d %lld\n", num[p], sum[p]);
}
}
}
return 0;
}


还有一种方法叫做”可持久化并查集“,随后补上。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: