• 并 查 集 ! ! !


    并查集的笔记

    (wtcl以至于只能发这种cj的内容)
    并查集,用于解决判断连通性。最好情况下应该是能达到log(n)级别的。这比dfs和bfs快多了啊啊啊啊啊。

    并查集,顾名思义,它分为两块:

    介绍大致思路

    用一个id数组,表示自己的爸爸是谁。这样一来,
    判断连通性的问题就转换成了看自己的爸爸是不是一个。
    上代码:

    typedef long long ll;
    ll n,m,x,y,z,id[N];
    

    合并

    比如说,x与y联通关系。
    那我们不妨令y是x的爸爸。
    那么,id[x]=y;用这句话就能让一个人轻松变你儿子。
    上代码:

    void unite(ll x,ll y){
    	ll xi=find(x),yi=find(y);
    	id[xi]=yi;
    }
    

    查找

    我们顺着儿子到爸爸的关系一个一个找下去:
    你要找x[i]的爸爸,就相当于找d[x[i]]的爸爸,一直找下去,总会到一个尽头。
    这个人,便是你爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸的爸爸。
    这个人就是你要找的祖先
    上代码:

    ll find(ll x){
    	if(id[x]==x)return x;
    	return id[x]=find(id[x]);
    }
    

    判连通

    假设有两个点:xi和yi
    你如果是连通的,那么xi的爸爸就等于y的爸爸。

    整体模板代码部分 ( 好激动 ) :

    #include<iostream>
    #define N 100010
    using namespace std;
    typedef long long ll;
    ll n,m,x,y,z,id[N];
    ll find(ll x){
    	if(id[x]==x)return x;
    	return id[x]=find(id[x]);
    }
    void unite(ll x,ll y){
    	ll xi=find(x),yi=find(y);
    	id[xi]=yi;
    }	
    int main(){
    	cin>>n>>m;
    	for(ll i=0;i<n;i++)id[i]=i;
    	while(m--){
    		cin>>z>>x>>y;
    		if(z==1) unite(x,y);
    		else if(z==2){
    			if(find(x)==find(y))cout<<"Y"<<endl;
    			else cout<<"N"<<endl;
    		}
    	}
    	return 0;
    }
    

    也就那么几行,不是特别难,对吧?

  • 相关阅读:
    <数据挖掘导论>读书笔记8FP树
    <数据挖掘导论>读书笔记7 Apriori算法
    c#:Json字符串转成xml对象
    微信公众平台开发
    一维随机变量及其概率分布
    概率的基本概念
    C#调用OCR组件识别图片文字
    增加系统右键菜单
    visual studio内置“iis”组件提取及二次开发
    《JavaScript权威指南》读书笔记——JavaScript核心
  • 原文地址:https://www.cnblogs.com/tushukai/p/11546291.html
Copyright © 2020-2023  润新知