C++中的Disjoint Set实现

Disjoint Set implementation in C++

本文关键字:实现 Set Disjoint 中的 C++      更新时间:2023-10-16

我在一次在线比赛中遇到了这个问题,我正试图使用Disjoint Set Data结构来解决它。

问题定义:

Bob在学校远足期间参观了一座核电站。他观察到,核电站中有n个核棒,核棒的初始效率为1。一段时间后,核棒开始相互融合并结合成一组。这个过程将核棒的效率降低到组大小的平方根。鲍勃是一个好奇的学生,他想知道一段时间后核电站的总效率。这是通过添加组的效率来获得的。

最初,所有的杆都属于其自己的尺寸为1的组。有f个融合。如果rod1和rod2融合,就意味着它们的组融合了。

样本输入:

5 2

12

2 3

样本输出:

3.73

解释:

n=5次融合=2次

组1,2,3=>1.73(sqrt(3))

第4组=>1

第5组=>1

总计=(1.73+1+1)=3.73

我的代码:

#include <iostream>
#include <set>
#include <vector>
#include <stdio.h>
#include <math.h>
#include <iomanip>
using namespace std;
typedef long long int lli;
vector<lli> p,rank1,setSize;   /* p keeps track of the parent
* rank1 keeps track of the rank
* setSize keeps track of the size of the set. 
*/ 
lli findSet(lli i) { return (p[i] == i) ? i : (p[i] = findSet(p[i])); } 
bool sameSet(lli x,lli y) { return findSet(x) == findSet(y); }

void union1(lli x,lli y) {      // union merges two sets.
if(!sameSet(x,y)) {
lli i = findSet(x), j = findSet(y);
if(rank1[i] > rank1[j]) {
p[j] = i;
setSize[i] += setSize[j];           
}
else {
p[i] = j;
setSize[j] += setSize[i];
if(rank1[i] == rank1[j])
rank1[j]++;
}
}
}
int main() {
freopen("input","r",stdin);
lli n;
cin >> n;                               //number of nuclear rods
setSize.assign(n,1);                    //Initialize the setSize with 1 because every element is in its own set
p.assign(n,0);          
rank1.assign(n,0);                      //Initialize ranks with 0's.
for(lli i = 0; i < n; i++) p[i] = i;    //Every set is distinct. Thus it is its own parent.
lli f;
cin >> f;                               //Number of fusions.
while(f--){                 
lli x,y;
cin >> x >> y;                      //combine two rods
union1(x,y);                        
}   
double ans; 
set<lli> s (p.begin(),p.end());         //Get the representative of all the sets.
for(lli i : s){     
ans += sqrt(setSize[i]);            //sum the sqrt of all the members of that set.
}
printf("n%.2f", ans);                  //display the answer in 2 decimal places.
}

上面的代码似乎适用于除一个以外的所有测试用例。

我的代码失败的输入就在这里。

预期输出为:67484.82

我的输出:67912.32

我真的不知道哪里出了问题,因为投入真的很大。

任何帮助都将不胜感激。提前谢谢。

p保存元素的直接父元素,而不是它们的findSet值。因此,当您执行set<lli> s (p.begin(),p.end());时,您可以在其中添加其他元素。

我可以想出两种方法来处理这个问题:

  1. 使用循环将findSet(i)插入到集合中,而不是直接放入p
  2. 执行setSize[i] += setSize[j]之后,请设置setSize[j] = 0。这样,中间的父母就不会为这笔钱捐款