基础数据结构(7)并查集

从零起步看算法(第二十二天 5.14)

//并查集

1.基本操作

简单理解就是,比爸爸,换爸爸,收儿子的方法。

1.初始化>>查找>>合并

2.路径压缩

3.带权并查集

点击打开链接

2.disjoint

树形的应用

#include <iostream>
using namespace std;

int father[110],n;
int dist[110],size[110];//dist 距离,//size 权重

void init(){
    for(int i=1;i<=n;++i){
        father[i]=i,dist[i]=0,size[i]=1;
    }
}
int get(int x){
    if(father[x]==x){
        return x;
    }
    int y=father[x];
    father[x]=get(y);//找到根节点
    dist[x]+=dist[y];
    return father[x];
}
void merge(int a,int b){
    a=get(a);
    b=get(b);
    if(a!=b){
        father[a]=b;
        dist[a]=size[b];
        size[b]+=size[a];//有几队
    }
}
int main() {
    n=10;
    init();//初始化
    merge(1,2);
    merge(10,7);
    merge(3,4);
    merge(3,7);
    get(1);
    cout<<dist[1]+1<<endl;
    get(3);
    cout<<dist[3]+1<<endl;
    return 0;
}

3.朋友

理解并查集的思想后,一切就没那么复杂了。

//朋友
#include<iostream>
#include<string>
using namespace std;

int father[5000+5];

void init(int n){//初始化 
	for(int i=1;i<=n;++i){
		father[i]=i;
	}
}

int get(int x){//找爸爸 
	if(father[x]==x){
		return x;
	}
	int y=father[x];
	father[x]=get(y);
	return father[x];
}

void merge(int a,int b){//换爸爸 
	a=get(a);
	b=get(b);
	if(a!=b){
		father[a]=b;
	}
}

void is_friend(int a,int b){
     if(get(a)==get(b))
	 {
	 	cout<<"Yes"<<endl;
	 }	
	else cout<<"No"<<endl;
}

 


int main(){
	
	int n,m,p;
	cin>>n>>m>>p;

	 init(n+5);
	 
	while(m--){
		int A1,B1;
		cin>>A1>>B1;
		merge(A1,B1);
	}
	
	while(p--){
		int A2,B2;
		cin>>A2>>B2;
		is_friend(A2,B2);
	}
	
	return 0;
}

4.网络交友

<set>,<map>,并查集的 ,综合题

//网络交友
#include<iostream>
#include<map>
#include<set>

using namespace std;

int father[10000+10];

void init(int n){
	for(int i=1;i<=n;i++)
	father[i]=i;
	
}
int get(int x){
	if(father[x]==x){
		return x;
	}
	int y=father[x];
	father[x]=get(y);
	return father[x];
}
void merge(int x,int y){
	int a=get(x);
	int b=get(y);
	if(a!=b){
		father[a]=b;
	}
}
int main(){
	int n;
	cin>>n;
	
	set<string> se;
	
	map<string ,int> ma;
	
	int p=1;
	
	init(n+10);
	
	
	while(n--){
		string a,b;
		cin>>a>>b;
		
		
		if(!se.count(a)){
			se.insert(a);
			ma[a]=p++;
		}
		if(!se.count(b)){
			se.insert(b);
			ma[b]=p++;
		}
		
		merge(ma[a],ma[b]);//并查集
		
		int ans=0;
		
		for(int i=1;i<p;i++){
			if(get(i)==get(ma[b]))
			ans++;
		} 
		cout<<ans<<endl;
	}
	return 0;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值