70分tle求调

P3367 【模板】并查集

leosana @ 2024-08-14 14:57:46

#include<iostream>
using namespace std;
const int maxn=1e4+5;
int fa[maxn];//存储父节点 
int find(int x){//寻找某个数字的父节点 
    if(x==fa[x]) return x;
     else return find(fa[x]);
}
int main(){
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        fa[i]=i;//将每个数的父节点定义为本身 
    }
    for(int i=1;i<=m;i++){
        int x,y,z;
        cin>>z>>x>>y; 
        if(z==2){
            if(find(x)!=find(y)){
                cout<<"N"<<endl;
            }else{
                cout<<"Y"<<endl;
            }

        }else{
            fa[find(x)]=find(y);//将x与y的父节点合并 

        }

    }

    return 0; 
} 

by _____QWQ_____ @ 2024-08-14 15:01:12

要用路径压缩的,不然爬树太慢了 @leosana


by dyyzy @ 2024-08-14 15:01:41

@leosana 考虑并查集优化吧,你这个是 \mathcal{O}(nm)


by _____QWQ_____ @ 2024-08-14 15:02:04

加一个赋值就可以了

#include<iostream>
using namespace std;
const int maxn=1e4+5;
int fa[maxn];//存储父节点 
int find(int x){//寻找某个数字的父节点 
    if(x==fa[x]) return x;
     else return fa[x]=find(fa[x]); ////直接把儿子连接到根节点上 
}
int main(){
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        fa[i]=i;//将每个数的父节点定义为本身 
    }
    for(int i=1;i<=m;i++){
        int x,y,z;
        cin>>z>>x>>y; 
        if(z==2){
            if(find(x)!=find(y)){
                cout<<"N"<<endl;
            }else{
                cout<<"Y"<<endl;
            }

        }else{
            fa[find(x)]=find(y);//将x与y的父节点合并 

        }

    }
}

@leosana


by Cosine_Func @ 2024-08-14 15:04:02

@leosana 可以考虑随机合并优化(


by dyyzy @ 2024-08-14 15:05:23

或者考虑按秩合并

fa[find(x)]=find(y);//将x与y的父节点合并 

改为


inline void merge(int u,int v){
    u=get(u),v=get(v);
    if(u==v)return;
    if(sz[u]<sz[v])swap(u,v);
    fa[v]=u,zs[u]+=sz[v];
}

其中 sz[] 维护了并查集节点个数


by qiuxiangyu2010 @ 2024-08-14 15:18:11

纯数组模拟了解一下:

#include<bits/stdc++.h>
using namespace std;
int n,m,a[10010];
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        a[i]=i;
    }
    int z,x,y;
    for(int i=1;i<=m;i++){
        cin>>z>>x>>y;
        if(z==1){
            for(int j=1;j<=n;j++){
                if(a[j]==a[y]&&j!=y){
                    a[j]=a[x];
                }
            }
            a[y]=a[x];
        }else{
            if(a[x]==a[y]){
                cout<<"Y\n";
            }else{
                cout<<"N\n";
            }
        }
    }
    return 0;
}

AC记录


by leosana @ 2024-08-14 18:04:00

AC了谢谢大家


by osmium_dust @ 2024-11-26 19:05:36

实测:cout改printf可以100


|