异或最小生成树

/*
	对于n个点的完全图,每两个点之间的距离等于两点的权值的异或和,求最小生成树
 */
int n;
struct XorTrie{
    int dfn = 0;
    int t[maxn*30][2];
    int L[maxn*30],R[maxn*30],val[maxn*30],a[maxn];
    void solve(){
    	sort(a+1, a+n+1);
    	for(int i = 1; i <= n; i++) Insert(a[i],i);
    	printf("%lld\n", Divide(0,32));
    }
    void Insert(ll x,int id){
        int rt = 0;
        for(int k=32;k>=0;k--){
            int op = (x>>k&1ll)?1:0;
            if(!t[rt][op]) t[rt][op] = ++dfn;
            rt = t[rt][op];
            if(!L[rt]) L[rt] = id;
            R[rt] = id;
        }
        val[rt] = x;
    }
    ll AnswerPos(int rt,int pos,ll x){
        for(int i=pos;i>=0;i--){
            int op = (x>>i&1ll)?1:0;
            if(t[rt][op]) rt = t[rt][op];
            else rt = t[rt][!op];
        }return rt;
    }
    void Traceback(int rt){
        printf("%d %d\n",L[rt],R[rt]);
        if(t[rt][0]) Traceback(t[rt][0]);
        if(t[rt][1]) Traceback(t[rt][1]);
    }
    ll Divide(int rt,int pos){
        if(t[rt][0]&&t[rt][1]){
            int x = t[rt][0],y = t[rt][1];
            ll minl = INF;
            for(int k=L[y];k<=R[y];k++){
                minl = min(minl,(ll)a[k]^val[AnswerPos(x,pos-1,a[k])]);
            }
            return minl+Divide(t[rt][0],pos-1)+Divide(t[rt][1],pos-1);
        }
        else if(t[rt][0]) return Divide(t[rt][0],pos-1);
        else if(t[rt][1]) return Divide(t[rt][1],pos-1);
        return 0;
    }
}trie;

例题有codeforces888G,和牛客多校第五场B Graph
888G
B Graph
代码如下:
888G:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define per(i, a, n) for(int i = n-1; i >= a; i--)
#define IOS std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define fopen freopen("file.in","r",stdin);freopen("file.out","w",stdout);
#define fclose fclose(stdin);fclose(stdout);
#define PI 3.14159265358979323846
const int inf = 1e9;
const ll INF = 1e18;
const int maxn = 2e5+10;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*f;
}
int n;
/*
	
 */
struct XorTrie{
    int dfn = 0;
    int t[maxn*30][2];
    int L[maxn*30],R[maxn*30],val[maxn*30],a[maxn];
    void solve(){
    	sort(a+1, a+n+1);
    	for(int i = 1; i <= n; i++) Insert(a[i],i);
    	printf("%lld\n", Divide(0,32));
    }
    void Insert(ll x,int id){
        int rt = 0;
        for(int k=32;k>=0;k--){
            int op = (x>>k&1ll)?1:0;
            if(!t[rt][op]) t[rt][op] = ++dfn;
            rt = t[rt][op];
            if(!L[rt]) L[rt] = id;
            R[rt] = id;
        }
        val[rt] = x;
    }
    ll AnswerPos(int rt,int pos,ll x){
        for(int i=pos;i>=0;i--){
            int op = (x>>i&1ll)?1:0;
            if(t[rt][op]) rt = t[rt][op];
            else rt = t[rt][!op];
        }return rt;
    }
    void Traceback(int rt){
        printf("%d %d\n",L[rt],R[rt]);
        if(t[rt][0]) Traceback(t[rt][0]);
        if(t[rt][1]) Traceback(t[rt][1]);
    }
    ll Divide(int rt,int pos){
        if(t[rt][0]&&t[rt][1]){
            int x = t[rt][0],y = t[rt][1];
            ll minl = INF;
            for(int k=L[y];k<=R[y];k++){
                minl = min(minl,(ll)a[k]^val[AnswerPos(x,pos-1,a[k])]);
            }
            return minl+Divide(t[rt][0],pos-1)+Divide(t[rt][1],pos-1);
        }
        else if(t[rt][0]) return Divide(t[rt][0],pos-1);
        else if(t[rt][1]) return Divide(t[rt][1],pos-1);
        return 0;
    }
}tire;
signed main(){
	n=read(); 
	for(int i = 1; i <= n; i++){
		tire.a[i]=read();
	}
	tire.solve();
	return 0;
}
 

B-Graph

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define per(i, a, n) for(int i = n-1; i >= a; i--)
#define IOS std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define fopen freopen("file.in","r",stdin);freopen("file.out","w",stdout);
#define fclose fclose(stdin);fclose(stdout);
#define PI 3.14159265358979323846
const int inf = 1e9;
const ll INF = 1e18;
const int maxn = 2e5+10;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*f;
}

/*
	对于n个点的完全图,每两个点之间的距离等于两点的权值的异或和,求最小生成树
 */
int n;
struct XorTrie{
    int dfn = 0;
    int t[maxn*30][2];
    int L[maxn*30],R[maxn*30],val[maxn*30],a[maxn];
    void solve(){
    	sort(a+1, a+n+1);
    	for(int i = 1; i <= n; i++) Insert(a[i],i);
    	printf("%lld\n", Divide(0,32));
    }
    void Insert(ll x,int id){
        int rt = 0;
        for(int k=32;k>=0;k--){
            int op = (x>>k&1ll)?1:0;
            if(!t[rt][op]) t[rt][op] = ++dfn;
            rt = t[rt][op];
            if(!L[rt]) L[rt] = id;
            R[rt] = id;
        }
        val[rt] = x;
    }
    ll AnswerPos(int rt,int pos,ll x){
        for(int i=pos;i>=0;i--){
            int op = (x>>i&1ll)?1:0;
            if(t[rt][op]) rt = t[rt][op];
            else rt = t[rt][!op];
        }return rt;
    }
    void Traceback(int rt){
        printf("%d %d\n",L[rt],R[rt]);
        if(t[rt][0]) Traceback(t[rt][0]);
        if(t[rt][1]) Traceback(t[rt][1]);
    }
    ll Divide(int rt,int pos){
        if(t[rt][0]&&t[rt][1]){
            int x = t[rt][0],y = t[rt][1];
            ll minl = INF;
            for(int k=L[y];k<=R[y];k++){
                minl = min(minl,(ll)a[k]^val[AnswerPos(x,pos-1,a[k])]);
            }
            return minl+Divide(t[rt][0],pos-1)+Divide(t[rt][1],pos-1);
        }
        else if(t[rt][0]) return Divide(t[rt][0],pos-1);
        else if(t[rt][1]) return Divide(t[rt][1],pos-1);
        return 0;
    }
}trie;
std::vector<pii> v[maxn];
void dfs(int rt, int pre){
	for(auto i : v[rt]){
		if(i.first==pre) continue;
		trie.a[i.first] = trie.a[rt]^i.second;
		dfs(i.first, rt);
	}
}
signed main(){
	n=read(); 
	for(int i = 1; i < n; i++){
		int x=read(), y=read(), z=read();
		x++,y++;
		v[x].push_back({y,z}), v[y].push_back({x,z});
	}
	dfs(1,0);
	trie.solve();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值