【vjudge训练记录】大一寒假专项训练——并查集

训练情况

A题

并查集模板,求班级最多人数和班级数,可以使用map进行统计,取父节点塞进map里面,取最大值和size即可

点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'

using namespace std;

const int N = 1e5 + 3;

int fa[N];

int n,m;

int Find(int x){
    if(fa[x] == x) return x;
    return fa[x] = Find(fa[x]);
}
 
void Union(int x,int y){
    x = Find(x); y = Find(y);
    if(x == y) return;
    fa[y] = x;
}

void solve(){
    cin>>n>>m;
    for(int i = 1;i<=n;i++) fa[i] = i;
    map<int,int> v;
    while(m--){
        int x,y; cin>>x>>y;
        Union(x,y);
    }
    for(int i = 1;i<=n;i++) v[Find(i)]++;
    int ma = 0;
    for(auto i:v) ma = max(ma,i.second);
    cout<<v.size()<<" "<<ma<<endl;
}

signed main(){
    // int T; cin>>T; while(T--)
    solve();
    return 0;
}

B题

并查集模板,判断是否在一个集合内,只需要查询两个点的父节点是否相同

点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'

using namespace std;

const int N = 2e5 + 3;

int n,m;
int fa[N];

int Find(int x){
    if(fa[x] == x) return x;
    return fa[x] = Find(fa[x]);
}

void Union(int x,int y){
    x = Find(x); y = Find(y);
    if(x == y) return;
    fa[y] = x;
}

void solve(){
    cin>>n>>m;
    for(int i = 1;i<=n;i++) fa[i] = i;
    while(m--){
        int opt,x,y; cin>>opt>>x>>y;
        if(opt == 1) Union(x,y);
        else if(opt == 2){
            if(Find(x) == Find(y)) cout<<"Y"<<endl;
            else cout<<"N"<<endl;
        }
    }
}

signed main(){
    // int T; cin>>T; while(T--)
    solve();
    return 0;
}

C题

维护亲戚的亲戚是亲戚这一传递关系,并查集模板

点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'

using namespace std;

const int N = 5e3 + 3;

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

int Find(int x){
    if(fa[x] == x) return x;
    return fa[x] = Find(fa[x]);
}

void Union(int x,int y){
    x = Find(x); y = Find(y);
    if(x == y) return;
    fa[y] = x;
}

void solve(){
    cin>>n>>m>>p;
    for(int i = 1;i<=n;i++) fa[i] = i;
    while(m--){
        int x,y; cin>>x>>y;
        Union(x,y);
    }
    while(p--){
        int x,y; cin>>x>>y;
        if(Find(x) == Find(y)) cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
}

signed main(){
    // int T; cin>>T; while(T--)
    solve();
    return 0;
}

D题

并查集模板,只是这次需要维护一下字符串和节点的映射关系,直接使用map维护

点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'

using namespace std;

const int N = 2e4 + 3;

int n,m;
int fa[N];
map<string,int> toi;

int Find(int x){
    if(fa[x] == x) return x;
    return fa[x] = Find(fa[x]);
}

void Union(int x,int y){
    x = Find(x); y = Find(y);
    if(x == y) return;
    fa[y] = x;
}

void solve(){
    cin>>n>>m;    
    for(int i = 1;i<=n;i++) fa[i] = i;
    int tot = 0;
    for(int i = 1;i<=n;i++){
        string s; cin>>s;
        toi[s] = ++tot;
    }
    while(m--){
        string x,y; cin>>x>>y;
        Union(toi[x],toi[y]);
    }
    int k; cin>>k;
    while(k--){
        string x,y; cin>>x>>y;
        if(Find(toi[x]) == Find(toi[y])) cout<<"Yes."<<endl;
        else cout<<"No."<<endl;
    }
}

signed main(){
    // int T; cin>>T; while(T--)
    solve();
    return 0;
}

E题

并查集模板,只是这次变成二维平面,点 \((x,y)\) 对应的节点是 \(n \times (x-1) + y\),其中 \(n\) 为行数

点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'

using namespace std;

const int N = 2e6 + 3;

int n,m,k;
int fa[N];

int Find(int x){
    if(fa[x] == x) return x;
    return fa[x] = Find(fa[x]);
}

void Union(int x,int y){
    x = Find(x); y = Find(y);
    if(x == y) return;
    fa[y] = x;
}

void solve(){
    cin>>n>>m>>k;
    for(int i = 1;i<=n*m;i++) fa[i] = i;
    while(k--){
        int x,y; cin>>x>>y;
        Union(x,y);
    }
    set<int> ans;
    for(int i = 1;i<=n*m;i++) ans.insert(Find(i));
    cout<<ans.size()<<endl;
}

signed main(){
    // int T; cin>>T; while(T--)
    solve();
    return 0;
}

F题

考察比较灵活的并查集,我们需要维护数字集合中的最大值,所以我们需要把父节点设为集合内数字的最大值+1,在每次修改数字的时候,直接查询父节点

点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'

using namespace std;

const int N = 1e6 + 3;

int fa[N];

int Find(int x){
    if(fa[x] == x) return x;
    return fa[x] = Find(fa[x]);
}

void solve(){
    int n; cin>>n;
    for(int i = 1;i<=N-3;i++) fa[i] = i;
    vector<int> a(n + 1);
    for(int i = 1;i<=n;i++) cin>>a[i];
    for(int i = 1;i<=n;i++){
        a[i] = Find(a[i]);
        fa[a[i]] = Find(a[i])+1;
        cout<<a[i]<<" ";
    }
}

signed main(){
    // int T; cin>>T; while(T--)
    solve();
    return 0;
}
posted @ 2025-01-24 19:14  MNNUACM_2024ZY  阅读(50)  评论(0)    收藏  举报