zoukankan      html  css  js  c++  java
  • Boruvka最小生成树算法

    在做 CF888G 的时候胡出来了这个东西,发现居然是个有名有姓的算法,震惊我一百年,故记之。

    算法流程

    引用某个课件(侵删)

    CF 888G

    和上面一样,只不过找最小值的时候用 Trie 来找,时间复杂度 (mathcal O(nlog nlog a_i+nlog^2 n))

    当然也可以直接贪心。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    inline int read()
    {
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return x*f;
    }
    const int N=3e5+10;
    typedef long long ll;
    int f[N],a[N];
    void init(int n){for(int i=1;i<=n;i++)f[i]=i;}
    int getf(int x){return f[x]==x?x:f[x]=getf(f[x]);}
    int trie[N*30][2],sz[N*30],ed[N*30],tot=0;
    void ins(int x,int pos)
    {
    	int p=0;
    	for(int i=29;i>=0;i--)
    	{
    		int op=(x&(1<<i))!=0;
    		if(!trie[p][op])trie[p][op]=++tot;
    		p=trie[p][op];
    		sz[p]++;
    	}
    	ed[p]=pos;
    }
    void del(int x)
    {
    	int p=0;
    	for(int i=29;i>=0;i--)
    	{
    		int op=(x&(1<<i))!=0;
    		p=trie[p][op];
    		sz[p]--;
    	}
    }
    int query(int x)
    {
    	int p=0;
    	for(int i=29;i>=0;i--)
    	{
    		int op=(x&(1<<i))!=0;
    		if(trie[p][op]&&sz[trie[p][op]])p=trie[p][op];
    		else p=trie[p][op^1];
    	}
    	return ed[p];
    }
    int n;ll ans=0; 
    vector<int> v[N];
    struct node
    {
    	int u,v,w;
    	bool operator <(const node &x)const {return w<x.w;}
    };
    void sol()
    {
    	int cnt=0;
    	for(int i=1;i<=n;i++)cnt+=getf(i)==i;
    	if(cnt==1)return;
    	for(int i=1;i<=n;i++)v[i].clear();
    	for(int i=1;i<=n;i++)v[getf(i)].push_back(i);
    	vector<node> s;
    	for(int i=1;i<=n;i++)
    	{
    		if(v[i].empty())continue;
    		int Min=0x7fffffff,pos=0,pos1=0;
    		for(int j=0;j<v[i].size();j++)
    		{
    			int x=v[i][j];
    			del(a[x]);
    		}
    		for(int j=0;j<v[i].size();j++)
    		{
    			int x=v[i][j],tmp=query(a[x]);
    			if((a[x]^a[tmp])<Min)Min=(a[x]^a[tmp]),pos=x,pos1=tmp;
    		}
    		s.push_back((node){pos,pos1,Min});
    		for(int j=0;j<v[i].size();j++)
    		{
    			int x=v[i][j];
    			ins(a[x],x);
    		}
    	}
    	sort(s.begin(),s.end());
    	for(int i=0;i<s.size();i++)
    	{
    		int u=s[i].u,v=s[i].v,w=s[i].w;
    		if(getf(u)!=getf(v))ans+=w,f[getf(v)]=getf(u);
    	}
    	sol();
    }
    signed main()
    {
    	n=read();init(n);
    	for(int i=1;i<=n;i++)a[i]=read();
    	sort(a+1,a+n+1);
    	n=unique(a+1,a+n+1)-a-1;
    	for(int i=1;i<=n;i++)ins(a[i],i);
    	sol();
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    Android JSON解析
    相对靠谱的相册、拍照返回选择程序
    android strings.xml转义字符,注意细节解决
    设置progressBar 背景以及进度条
    Android Launcher简易Launcher开发
    android.os.NetworkOnMainThreadException 异常处理
    AspNetPager 多条件分页查询
    无法解析指定对象的 TargetProperty (UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)“的异常解决
    DefaultButton Deal with users hitting ENTER on your forms
    Setup SSRS in SharePoint Integrated Mode
  • 原文地址:https://www.cnblogs.com/juruo-zzt/p/14809430.html
Copyright © 2011-2022 走看看