P3367 【模板】并查集

题目链接 https://www.luogu.com.cn/problem/P3367

并:合并。将两个不相交的集合合并,合并时需要先查找。

查:查找。查找两个节点是否在同一集合内,也就是根节点是否相同。

集:集合。将新加入的点的根节点更新。

并查集:用来检查一个图是否存在环;合并合集或者判断是否有相同的祖先关系,可以将不同的元素合并到同一个集合中,想查询的时候直接查询。


 

parent[i]表示i结点的父节点

rankp[i]记录深度,表示i所在的层数。避免一条长链式的结构导致查找路径时非常慢,可以引用rankp数组对此优化。


 

查找根节点:

int Getparent(int o)
{
    if(o == parent[o])
        return o;
    else
    {
        parent[o] = Getparent(parent[o]);  //父节点设为根节点
        return parent[o];         //返回父节点
    }
}

可以简写为:

int Getparent(int o)
{
    return o == parent[o] ? o : (parent[o] = Getparent(parent[o]));
}

合并:

void Union(int x,int y)
{
    int x_root=Getparent(x);
    int y_root=Getparent(y);
    if(x_root!=y_root)
        parent[y_root]=x_root;//左靠,将右边的集合作为左边的子集
    return;
}

可以优化为:

int Union(int x,int y,int parent[],int rankp[])
{
    int x_root=Getparent(x);
    int y_root=Getparent(y);
    if(x_root==y_root) return 0;
    else
    {
        if(rankp[x_root]>rankp[y_root])
            parent[y_root]=x_root;
        else if(rankp[y_root]>rankp[x_root])
            parent[x_root]=y_root;
        else
        {
            parent[x_root]=y_root;
            rankp[y_root]++;
        }
        return 1;
    }

 

放AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 long long n,m;
 4 int z,x,y;
 5 int parent[20010];
 6 int rankp[20010];
 7 
 8 //找根节点
 9 inline int Getparent(int o)
10 {
11     if(parent[o]==o) return o;
12     else return parent[o]=Getparent(parent[o]);//路径压缩
13 }
14 
15 //合并
16 inline int Union(int x,int y,int parent[],int rankp[])
17 {
18     int x_root=Getparent(x);
19     int y_root=Getparent(y);
20     if(x_root==y_root) return 0;
21     else//优化部分
22     {
23         if(rankp[x_root]>rankp[y_root])
24             parent[y_root]=x_root;
25         else if(rankp[y_root]>rankp[x_root])
26             parent[x_root]=y_root;
27         else
28         {
29             parent[x_root]=y_root;
30             rankp[y_root]++;
31         }
32         return 1;
33     }
34 }
35 
36 //是否在同一子集
37 inline void Find(int x,int y)
38 {
39     int x_root=Getparent(x);
40     int y_root=Getparent(y);
41     if(x_root==y_root) cout<<"Y"<<endl;
42     else cout<<"N"<<endl;
43 }
44 
45 int main()
46 {
47     ios::sync_with_stdio(false);
48     memset(rankp,0,sizeof(rankp));
49     cin>>n>>m;
50     for(register int i=1;i<=n;i++)
51         parent[i]=i;
52     for(register int i=1; i<=m; i++)
53     {
54         cin>>z>>x>>y;
55         if(z==1) Union(x,y,parent,rankp);
56         else Find(x,y);
57     }
58     return 0;
59 }

 

posted @ 2022-04-15 14:42  爱吃虾滑  阅读(74)  评论(0)    收藏  举报