天梯赛 · 并查集

(1)朴素并查集:=》只判连通

cpp 复制代码
int p[N];              // 存储每个点的祖宗节点

// 查找 + 路径压缩(核心)
int find(int x)
{
    if (p[x] != x) 
        p[x] = find(p[x]);  // 路径直接挂到根节点
    return p[x];
}

// 初始化:每个点自己是根
for (int i = 1; i <= n; i ++ ) 
    p[i] = i;

// 合并 a 和 b 所在集合
p[find(a)] = find(b);

(2)带集合大小的并查集:=》统计集合元素个数(连不连通 + 集合多大)

cpp 复制代码
int p[N], size[N];    
// p[]:存储每个点的祖宗节点
// size[]:只有祖宗节点有效,表示当前集合的元素数量

// 查找 x 的根节点 + 路径压缩
int find(int x)
{
    if (p[x] != x) 
        p[x] = find(p[x]);
    return p[x];
}

// 初始化:每个点自己是根,集合大小为 1
void init(int n)
{
    for (int i = 1; i <= n; i ++ )
    {
        p[i] = i;
        size[i] = 1;
    }
}

// 合并 a 和 b 所在的集合
void merge(int a, int b)
{
    int fa = find(a);
    int fb = find(b);
    if (fa != fb)
    {
        // 先更新集合大小,再修改父节点(顺序不能变)
        size[fb] += size[fa];
        p[fa] = fb;
    }
}

(3)维护到祖宗节点距离的并查集:=》维护点到根的距离/关系(连不连通 + 两点之间距离 / 关系)

cpp 复制代码
int p[N], d[N];        
// p[x]:存储节点 x 的父节点
// d[x]:存储 x 到其父节点 p[x] 的距离/权值(find后表示x到根节点的距离)

// 查找 x 的根节点 + 路径压缩 + 维护距离
int find(int x)
{
    if (p[x] != x)
    {
        // 先递归找到根节点 u
        int u = find(p[x]);
        // 更新 x 到根节点的距离
        d[x] += d[p[x]];
        // 路径压缩:直接把 x 挂到根节点上
        p[x] = u;
    }
    return p[x];
}

// 初始化:每个节点自己是根,到父节点距离为 0
void init(int n)
{
    for (int i = 1; i <= n; i ++ )
    {
        p[i] = i;
        d[i] = 0;
    }
}

// 合并 a 和 b 所在集合(根据题目自定义 distance)
void merge(int a, int b, int distance)
{
    int fa = find(a);
    int fb = find(b);
    if (fa != fb)
    {
        p[fa] = fb;
        d[fa] = distance;  // 核心:设置根 fa 到根 fb 的权值
    }
}

L2-024 部落

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4+10;
int p[N];
int find(int x){
    if(p[x]!=x){
        p[x]=find(p[x]);
    }
    return p[x];
}
int main(){
    int n;
    int maxnum = 0;
    if(!(cin>>n)) return 0;
    for(int i = 0;i<N;i++) p[i] = i;
    for(int i = 0 ;i <n;i++){
        int k;
        if(!(cin>>k)) return 0;
        vector<int> a(k);
        for(int j = 0;j<k;j++ ){
            int x;
            cin>>x;
            if(x>maxnum) maxnum = x;
            a[j] = x;
        }
        if(k<2) continue;
     
        for(int j = 0;j<k-1;j++){
            int x = find(a[j]);
            int y = find(a[j+1]);
            if(x!=y){
                p[y] = x;
            }
        }
    }
    set<int> mp;
    //p[i] = 父节点,不一定是根
    //find(i) = 一定是根
    for(int i = 1;i<=maxnum;i++){
        mp.insert(find(i));
    }
    cout<<maxnum<<" "<<mp.size()<<endl;
    int q;
    cin>>q;
    while(q--){
        int x,y;
        cin>>x>>y;
        if(find(x)==find(y)) cout<<"Y\n";
        else cout<<"N\n";
    }
    return 0;
}

L3-003 社交集群

cpp 复制代码
#include<iostream>
#include<map>
#include<set>
using namespace std;
int f[1005], p[1005];
map<int, int> mp;
multiset<int, greater<int>> st;
int find(int x){
    if(f[x]==x) return f[x];
    return f[x]=find(f[x]);
}
void merge(int x, int y){
    int a=find(x), b=find(y);
    if(a!=b) f[b]=a;
}
int main(){
    for(int i=0; i<1005; i++) f[i]=i;
    char _;
    int n, k, h;
    cin >> n;
    for(int i=1; i<=n; i++){
        cin >> k >> _ >> p[i];
        while(--k){
            cin >> h;
            merge(p[i], h);
        }
    }for(int i=1; i<=n; i++) mp[find(p[i])]++;
    for(auto q:mp) st.insert(q.second);
    cout << st.size() << "\n" << *st.begin();
    st.erase(st.begin());
    for(auto q:st) cout << ' ' << q;
    cout << "\n";
}
相关推荐
ting94520003 小时前
Humalike X Hermes 深度技术剖析:单指令注入群聊社交智能的底层架构、算法与跨 IM 平台实现
人工智能·算法·架构
吴声子夜歌3 小时前
Java面试——算法
java·算法·面试
h_a_o777oah4 小时前
【图论】Tarjan 缩点:解决有向图中环的问题
c++·算法·图论·acm·强连通分量·缩点·tarjan
Tisfy4 小时前
LeetCode 1386.安排电影院座位:哈希表+位运算
算法·leetcode·散列表·题解·哈希表
Nil2084 小时前
leetcode 199二叉树的右视图
算法·leetcode·深度优先
M78佐菲5 小时前
c语言学习笔记:排序与查找方法整理
linux·c语言·笔记·学习·算法
AI备案指南-满满7 小时前
人工智能拟人化互动服务安全自评估报告的评估要点有哪些?
人工智能·算法·安全·机器人·大模型备案·算法备案
LuminousCPP7 小时前
数据结构‑二叉树(二):二叉堆从零实现|Heap结构设计 + 建堆优化 + 堆排序深度解析
c语言·数据结构·笔记·二叉树
土司大王9 小时前
LeetCode hot100——两两交换链表中的节点
算法·leetcode·职场和发展