并查集

AcWing 836. 合并集合

题目链接
https://www.acwing.com/problem/content/838/

解析
并查集的代码模板很短很好写,本题重点学习读入hh

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1e5 + 10;

int n, m;
int p[N];

//带路径压缩的find,路径压缩后可以近乎O(1)
int find(int x){
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) p[i] = i;
    
    while(m --){
        char c;
        int a, b;
        scanf("\n%c %d %d", &c, &a, &b);
        int pa = find(a), pb = find(b);
        if(c == 'M') p[pa] = pb;
        else if(c == 'Q'){
            if(pa == pb) puts("Yes");
            else puts("No");
        }
    }
    return 0;
}

AcWing 837. 连通块中点的数量

题目链接
https://www.acwing.com/problem/content/839/

解析

  • 本题在进行并查集操作的同时维护了集合中的节点数量cnt[i]
  • 易错点在于询问中的a和b可能是同一点
  • 本题还要学习读入

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1e5 + 10;

int n, m;
int p[N], cnt[N];

int find(int x){
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) p[i] = i, cnt[i] = 1;
    
    while(m --){
        int a, b;
        string op;
        cin >> op;
        if(op == "C"){
            scanf("%d%d", &a, &b);
            int pa = find(a), pb = find(b);
            if(pa != pb){
                p[pa] = pb;
                cnt[pb] += cnt[pa];
            }
        }
        else if(op == "Q1"){
            scanf("%d%d", &a, &b);
            int pa = find(a), pb = find(b);
            if(pa == pb) puts("Yes");
            else puts("No");
        }
        else if(op == "Q2"){
            scanf("%d", &a);
            int pa = find(a);
            printf("%d\n", cnt[pa]);
        }
    }
    return 0;
}

ABC238 E - Range Sums

题目链接
https://atcoder.jp/contests/abc238/tasks/abc238_e

解析

  • 题目给出(l, r)的区间和的值,意味着可以在前缀和s[l - 1]和s[r]之间建立一条边(二者可以相互求解)
  • 问题转化为判断最终是否可以在0与n之间是否连通
  • 注意该题不是连通图而是并查集,可以模拟样例体会

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
 
using namespace std;
 
typedef long long ll;
 
ll a, s;
int t;
 
int main()
{
    scanf("%d", &t);
    while(t --)
    {
        scanf("%lld%lld", &a, &s);
        if(s - 2 * a >= 0 && ((s - 2 * a) & a) == 0) puts("Yes");
        else puts("No");
    }
    return 0;
}
posted @   小菜珠的成长之路  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示