Clover_INF @ 2019-07-23 14:45:05
求助大佬,我的并查集不知为何只有40分,请大佬给我指点一下,谢谢
#include<cstdio>
#include<cstring>
using namespace std;
int a[10001];
int find(int x)
{
int k = x, p = x;
while(a[k] > -1) {
k = a[k];
}
while(a[p] > -1) {
int temp = a[p];
a[p] = k;
p = temp;
}
return k;
}
void Union(int root1, int root2)
{
int temp = a[root1] + a[root2];
if(a[root2] < a[root1]) {
a[root1] = root2;
a[root2] = temp;
}
else {
a[root2] = root1;
a[root1] = temp;
}
}
int main()
{
int n, m;
memset(a, -1, sizeof(a));
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++)
{
int z, x, y;
scanf("%d%d%d", &z, &x, &y);
if(z == 1) Union(find(x), find(y));
else {
if(find(x) == find(y)) printf("Y\n");
else printf("N\n");
}
}
return 0;
}
by Lupus @ 2019-07-23 15:00:10
void Union(int root1, int root2)
{
int temp = a[root1] + a[root2];
if(a[root2] < a[root1]) {
a[root1] = root2;
a[root2] = temp;
}
else {
a[root2] = root1;
a[root1] = temp;
}
}
冒昧的问一句,请问您为什么要新建一个节点呢??
by Raw_Aya9285 @ 2019-07-23 15:03:42
@焦铭扬 主函数没问题 合并和查找的函数貌似都有问题
by Raw_Aya9285 @ 2019-07-23 15:04:34
诶不对 好像主函数也有问题
by Raw_Aya9285 @ 2019-07-23 15:12:05
@焦铭扬
find部分只用简单地判断:
if(a[x]!=x){ //如果祖先不是本身
a[x]=find(a[x]); //就继续找祖先
}
return a[x]; //返回祖先
这样就可以了。
为了配合这段函数,主函数的初始化应该是这样:
for(int i=1;i<=n;i++){
a[i]=i; //一开始每个人的祖先都是自己
}
另外合并函数内也只需要简单判断是否相同就可以了,大概如下:
int r1=find(root1),r2=find(root2);
if(r1!=r2){
a[r2]=r1;
}
by Clover_INF @ 2019-07-23 15:19:39
@fishsause 我的并查集是每个的根节点存的是这个树元素的个数的复数,子节点存的是其父节点的下标,一开始每个人的祖先都是自己,所以都制成-1,而我第二个find函数是为了路径优化。我只过了4个,剩下的都是RE