您的位置:首页 > 理论基础 > 数据结构算法

poj 1988 Cube Stacking(数据结构:带权并查集)

2014-07-24 21:39 453 查看
一道比较入门的题...

早就应该写出来了,因为傻逼了在这调了几个小时,最后还是看的别人代码

题意是给出一个指令M a b

把含有a的一列箱子摞在含有b的一列箱子上面

我傻逼就傻逼在老想着检查当前每个箱子下面箱子的个数

但问题在于需要下一次输入时才会更新当前位置下方箱子的个数

结果用vector写一直超内存

这个题的解法很简单,就是记录每个箱子的父节点p、下方箱子的个数d、这一列箱子的总数s

在路径压缩的过程中,每个节点的d值要加上父节点的d值

代码如下:

#include <cstdio>
#define MAXN 30002
using namespace std;

int d[MAXN], s[MAXN], p[MAXN];

int find(int x) {
int tmp;
if(p[x] != x) {
tmp = p[x];
p[x] = find(p[x]);
d[x] += d[tmp];
}
return p[x];
}

int main(void) {
int T, i, x, y, t1, t2, tmp;
char ch[10];
scanf("%d", &T);
for(i=1; i<=MAXN; ++i) {
p[i] = i;
d[i] = 0;
s[i] = 1;
}
while(T--) {
scanf("%s", ch);
if(ch[0] == 'M') {
scanf("%d%d", &x, &y);
t1 = find(x);
t2 = find(y);
p[t1] = t2;

d[t1] += s[t2];
s[t2] += s[t1];
} else {
scanf("%d", &x);
find(x);
printf("%d\n", d[x]);
}
/*
for(i=1; i<=6; ++i) {
printf("\n%d_______%d - down: %d\tsum: %d\n", 6-T, i, d[i], s[i]);
}
*/
}
return 0;
}


再附上我用vector写的,记录当前节点的每个孩子,当并入另一集合时更新所有孩子节点的d值

方法应该是不会错的,但是超内存了,后来改用数组写还是超内存

代码如下:

#include <vector>
#include <cstdio>
#include <iostream>
#include <iterator>
#include <algorithm>
#define MAXN 30002
using namespace std;

int d[MAXN], s[MAXN], p[MAXN];
vector<int> v[MAXN];
vector<int>::iterator it;

int find(int x) {
return x==p[x] ? p[x] : p[x]=find(p[x]);
}

void Union(int x, int dx) {
for(it = v[x].begin(); it!=v[x].end(); ++it) {
if(*it != x)
d[*it] += dx;
}
}

int main(void) {
int T, i, x, y, t1, t2, tmp;
char ch[10];
while(scanf("%d", &T) != EOF) {
for(i=1; i<MAXN; ++i) {
p[i] = i;
v[i].clear();
d[i] = 0;
s[i] = 1;
}
while(T--) {
scanf("%s", ch);
if(ch[0] == 'M') {
scanf("%d%d", &x, &y);
t1 = find(x);
t2 = find(y);
Union(t1, s[t2]);
p[t1] = t2;

v[t2].push_back(t1);
for(it=v[t1].begin(); it!=v[t1].end(); ++it)
v[t2].push_back(*it);

v[t1].clear();

d[t1] += s[t2];
s[t2] += s[t1];
s[t1] = 0;
} else {
scanf("%d", &x);
printf("%d\n", d[x]);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: