zoukankan      html  css  js  c++  java
  • luoguP3367 [模板]并查集

    题目链接:https://www.luogu.org/problemnew/show/P3367

    思路:

    今天学了新算法——并查集,本题是简单的并查集题的模板。

    核心思想是“递归+压缩路径”。

    并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内赛题中,其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运行的时间复杂度也极高,根本就不可能在比赛规定的运行时间(1~3秒)内计算出试题需要的结果,只能用并查集来描述。 (摘自百度)

    我们用祖宗和他的子孙表示一个集合,所以先初始化为每个数字的祖宗就是他自己,有n个独立的集合。

    合并操作:通过get函数得到k的祖宗,并进行路径压缩,使一个集合中所有元素的祖宗只有一个,这样复杂度就是O(logn)。所以合并时直接将y的祖宗变成z的祖宗,之后再压缩路径就行了。

    查询操作:直接判断y的祖宗与z的祖宗是否想等即可


    下面的代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 int n,m,x,y,z;
     5 int f[10005];
     6 
     7 int get(int k){
     8     if(f[k]==k) return k;
     9     else return f[k]=get(f[k]);   //压缩路径
    10 }
    11 
    12 int main(){
    13     scanf("%d%d",&n,&m);
    14     for(int i=1;i<=n;i++)
    15         f[i]=i;                   //初始化
    16     while(m--){
    17         scanf("%d%d%d",&x,&y,&z);
    18         if(x==1){
    19             f[get(y)]=get(z);     //将y的祖宗变成z的祖宗
    20         }
    21         else{
    22             if(get(y)==get(z))   //判断y的祖宗是否等于z的祖宗
    23                 printf("Y
    ");
    24             else
    25                 printf("N
    ");
    26         }
    27     }
    28     return 0;
    29 }
  • 相关阅读:
    [USACO08MAR]土地征用Land Acquisition
    树链剖分
    [AHOI2008]紧急集合 / 聚会
    P1852 [国家集训队]跳跳棋
    Ant Trip(欧拉回路+并查集)
    单词游戏
    POJ3694 Network
    C++ STL小总结
    2-Sat专题
    6大名家带你穿越大半个中国去深思
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/10350380.html
Copyright © 2011-2022 走看看