并查集模板题

简介: 并查集模板题

首先我们知道并查集是为了解决一些元素分组的问题。它管理一系列不相交的集合,并支持两种操作: 合并(Union):把两个不相交的集合合并为一个集合。查询(Find):查询两个元素是否在同一个集合中。

下面是一道模板题。


题目如下:


维护一个 n 点的无向图,支持:

  • 加入一条连接 u 和 v 的无向边
  • 查询 u和 v的连通性


由于本题数据较大,因此输出的时候采用特殊的输出方式:用 0 或 1代表每个询问的答案,将每个询问的答案依次从左到右排列,把得到的串视为一个二进制数,输出这个二进制数 mod 998244353 的值。

请务必使用快读。


输入格式


第一行包含两个整数 n,m表示点的个数和操作的数目。

接下来 m 行每行包括三个整数 op,u,v。

  • 如果 op=0,则表示加入一条连接 u 和 v 的无向边;
  • 如果 op=1,则表示查询 u 和 v 的连通性。


输出格式

一行包括一个整数表示答案。


样例

Input Output
1. 3 6
2. 1 1 0
3. 0 0 1
4. 1 0 1
5. 1 1 2
6. 0 2 1
7. 1 2 1
5


答案串为 0101。

数据范围与提示

n≤4000000,m≤8000000


下面我们分析一下这个题目;


拿样例解释一下;比如开头1 1 0;就代表查询1 0,是否连接,不连接就输出0,而后面的 0 0 1,表示连接 0 1,所以后面的1 0 1,在查询后显示0 1连接即输出1,依此类推,得到答案串0101;


下面是ac代码,关建点都有注释。

f58230e9f063709cf3167704f4efdf14.gif


学习算法

#include<iostream>
using namespace std;
int father[4000000];
long long ans=0;
int k=1;
int temp;
const long long mod=998244353;
int find(int k)//父亲节点
{
  if(father[k]!=k)//这里的意思是如果一个节点不等于他自己就不是根节点,然后递归 
    return find(father[k]);
  return father[k];
}
void unionn(int x,int y)//连接
{
  x=find(x);
  y=find(y);
  if(x!=y)
    father[y]=x;
} 
int main()
{
  int m,n,i,a,b,s1,s2,op;
cin>>n>>m;
  for(i=1;i<=n;i++)//先自己就是自己的父亲节点
    father[i]=i;
  for(i=1;i<=m;i++)
  {
    scanf("%d %d %d",&op,&a,&b);
    if(op==0)
    {
      unionn(a,b);//连接边
    }
    else
    {
      if(find(a)==find(b))//如果父亲节点相同
      {
        ans*=2;
        ans++;
        ans%=mod;
      }
      else
      {
        ans*=2;
        ans%=mod;
      }
    }
  } 
  cout<<ans<<endl;//ok
}

f58230e9f063709cf3167704f4efdf14.gif


学习算法

相关文章
|
8月前
|
算法
并查集,路径压缩
并查集,路径压缩
51 0
|
8月前
并查集。。
并查集。。
41 0
|
8月前
|
机器学习/深度学习
并查集(UnionFind)总结
并查集(UnionFind)总结
78 0
|
算法
数星星(树状数组模板题)
数星星(树状数组模板题)
74 0
Trie树,并查集的简单应用(AcWing)
Trie树,并查集的简单应用(AcWing)
98 0
|
存储 算法 iOS开发
并查集详解及应用
并查集详解及应用
3862 0
|
存储 Python
【23. 并查集】
**用途**: - 将俩个集合合并 - 询问俩个元素是否在一个集合当中 **基本原理**: - 每个集合用一棵树来表示。树根的编号就是整个集合的编号,每个节点存储它的父节点,`p[x]`表示x的父节点。
131 0
【23. 并查集】