2020牛客暑期多校第三场 G Operating on a Graph(并查集+启发式合并)

题目链接


显然我们需要保存所有的点集,判断是否需要遍历所有的点就是看它本身是否是祖先节点。如果不是每次遍历该集合的连接点然后合并集合外的元素,合并之后既可以清空

启发式合并

#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define lowbit(x) (x&(-x))
#define mkp(x,y) make_pair(x,y)
#define mem(a,x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const double dinf=1e300;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=8e5+10;
  
vector<int> q[maxn];
int f[maxn];
  
int Find(int x){
    return f[x]==x?x:f[x]=Find(f[x]);
}
  
void Union(vector<int> &x,vector<int> &y){
    if(x.size()<y.size()) swap(x,y);
    for(auto i: y) x.push_back(i);
}
  
int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    //ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t,n,m,x,T;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++){
            f[i]=i;
            q[i].clear();
        }
        for(int i=0,u,v;i<m;i++){
            scanf("%d%d",&u,&v);
            q[u].pb(v),q[v].pb(u);
        }
        scanf("%d",&T);
        while(T--){
            scanf("%d",&x);
            if(Find(x)!=x) continue;
            vector<int> cur=q[x];
            q[x].clear();
            for(auto i: cur){
                int fi=Find(i);
                if(fi!=x){
                    f[fi]=x;
                    Union(q[x],q[fi]);
                    q[fi].clear();
                }
            }
  
        }
        for(int i=0;i<n;i++) printf("%d%c",Find(i),i==n-1?'\n':' ');
    }
    return 0;
}

list

因为 l i s t list list S T L STL STL维护的双向链表,所有此题用 l i s t list list操作会更少,只是好像没有启发式合并快

#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define lowbit(x) (x&(-x))
#define mkp(x,y) make_pair(x,y)
#define mem(a,x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const double dinf=1e300;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=8e5+10;

list<int> q[maxn];
int f[maxn];

int Find(int x){
    return f[x]==x?x:f[x]=Find(f[x]);
}

int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    //ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t,n,m,x,T;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++){
            f[i]=i;
            q[i].clear();
        }
        for(int i=0,u,v;i<m;i++){
            scanf("%d%d",&u,&v);
            q[u].pb(v),q[v].pb(u);
        }
        scanf("%d",&T);
        while(T--){
            scanf("%d",&x);
            if(Find(x)!=x) continue;
            list<int> cur=q[x];
            q[x].clear();
            for(auto i: cur){
                int fi=Find(i);
                if(fi!=x){
                    f[fi]=x;
                    q[x].splice(q[x].end(),q[fi]);
                    q[fi].clear();
                }
            }
        }
        for(int i=0;i<n;i++) printf("%d%c",Find(i),i==n-1?'\n':' ');
    }
    return 0;
}

你可能感兴趣的:(牛客比赛)