zoukankan      html  css  js  c++  java
  • 并查集

    并查集

    并查集朴素实现:

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

    路径压缩

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

    在朴素实现的过程中,复杂度较高,而路径压缩的复杂度为 (O(α(n))) ,可近似认为其复杂度为常数级别

    但是路径压缩的做法是把所有的子节点都直接与根节点相连,会破坏树的原始结构

    拓展域

    对于多种关系的处理,我们可以将其合并范围增大,以表示不同的合并关系

    (1) ~ (n) 范围表示A类,(n+1) ~ (2n) 范围表示B类,(2n+1) ~ (3n) 范围表示C类
    之后按照题目的食物链关系合并即可

    code

    #include<iostream>
    #include<cstdio>
    #include<math.h>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    
    const ll maxn=5e4+10;
    ll fa[3*maxn];
    ll n,k,a,b,ans;
    
    inline ll find(ll x)
    {
    	if(fa[x]==x) return x;
    	else return fa[x]=find(fa[x]);
    }
    
    int main(void)
    {
    	scanf("%lld %lld",&n,&k);
    	
    	for(int i=1;i<=n*3;i++) fa[i]=i;
    	for(int i=1;i<=k;i++)
    	{
    		ll op,x,y;
    		scanf("%lld %lld %lld",&op,&x,&y);
    		
    		if(x>n||y>n)
    		{
    			ans++;
    			continue;
    		}
    		if(op==1)
    		{
    			if(find(x+n)==find(y)||find(x+n+n)==find(y)) ans++;
    			else
    			{
    				fa[find(x)]=find(y);//同类 
    				fa[find(x+n)]=find(y+n);//同类 
    				fa[find(x+n+n)]=find(y+n+n);//同类 
    			}
    		}
    		if(op==2)
    		{
    			if(x==y)
    			{
    				ans++;
    				continue;
    			}
    			if(find(x)==find(y)||find(x)==find(y+n+n)) ans++;
    			else
    			{
    				fa[find(x+n)]=find(y+n+n);//B->C
    				fa[find(x)]=find(y+n);//A->B
    				fa[find(x+n+n)]=find(y);//C->A
    			}
    		}
    	}
    	
    	printf("%lld
    ",ans);
    	
    	return 0;
    }
    

    边带权

    即在路径压缩的基础上,在进行合并之前,先对边权进行一些处理,之后再进行合并的操作

    code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<math.h>
    #include<vector>
    #include<queue>
    #define ll long long
    using namespace std;
    
    const ll maxn=3e4+10;
    ll t,x,y;
    char op;
    ll fa[maxn],dis[maxn],siz[maxn];
    
    inline ll find(ll x)
    {
    	if(fa[x]==x) return x;
    	ll rot=find(fa[x]);
    	dis[x]+=dis[fa[x]];
    	return fa[x]=rot;
    } 
    
    inline void upd(ll x,ll y)
    {
    	ll ex=find(x),ey=find(y);
    	fa[ex]=ey;
    	dis[ex]=siz[ey];
    	siz[ey]+=siz[ex];
    }
    
    int main(void)
    {
    	ios_base::sync_with_stdio(0);
    	cin.tie(0);
    	cout.tie(0);
    	
    	for(int i=1;i<=maxn;i++) fa[i]=i,siz[i]=1;
    	memset(dis,0,sizeof(dis));
    	
    	cin>>t;
    	
    	while(t--)
    	{
    		cin>>op>>x>>y;
    		
    		if(op=='M')
    		{
    			upd(x,y);
    		}
    		if(op=='C')
    		{
    			ll ex=find(x),ey=find(y);
    			if(ex!=ey)
    			{
    				cout<<"-1"<<'
    ';
    				continue;
    			}
    			else
    			{
    				if(x==y)
    				{
    					cout<<"0"<<'
    ';
    					continue;
    				}
    				cout<<abs(dis[x]-dis[y])-1<<'
    ';
    			}
    		}
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    ubuntu19.04 redis启动和停止及连接
    ubuntu Redis安装及配置
    Django 基本使用及目录结构
    selenium设置chrome请求头
    多进程爬虫python——实例爬取酷狗歌单
    2020第一周学习记录
    爬取博客园最新文章
    python下用selenium的webdriver包如何在执行完点击下一页后没有获得下一页新打开页面的html源代码
    质量属性六个常见属性《钉钉》场景分析
    warnings.warn('Selenium support for PhantomJS has been deprecated, please use headless '报错
  • 原文地址:https://www.cnblogs.com/jd1412/p/14084793.html
Copyright © 2011-2022 走看看