最长异或路径(01trie+最大异或对)

最长异或路径

板子题,但是如果把边权改成了点权的话好像就不好做了,暂时还没想好

题意:给定一棵带边权的树,求最大的异或路径。

思路

  1. 令每个节点的权值为从根到当前节点的路径上边权异或值,则此问题就被转化为普通的最大异或对了
  2. 最大异或对就没啥说的了,按顺序(随便什么顺序)把每个点加入 01 t r i e 01trie 01trie中,然后在每加入一个点前先判定当前点能与 01 t r i e 01trie 01trie中异或的最大值(贪心得搞一下就行了),把所有求出的最大值再取一个最大值就是答案了

题面描述

#include "bits/stdc++.h"
#define hhh printf("hhh\n")
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {int x=0;char c=getchar();while(c<'0'||c>'9')c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return x;}

const int maxn = 1e5+10;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const double eps = 1e-7;

int N;
int head[maxn], nxt[maxn*2], to[maxn*2], w[maxn*2], tot;
int a[maxn];
int node[maxn<<5][2], cnt;

inline void add_edge(int u, int v, int w) {
    ++tot, to[tot]=v, nxt[tot]=head[u], ::w[tot]=w, head[u]=tot;
    ++tot, to[tot]=u, nxt[tot]=head[v], ::w[tot]=w, head[v]=tot;
}

inline void max(int &a, int b) { if(a<b) a=b; }

void dfs(int u, int fa) {
    for(int i=head[u]; i; i=nxt[i]) {
        int v=to[i];
        if(v!=fa) {
            a[v]=a[u]^w[i];
            dfs(v,u);
        }
    }
}

inline void insert(int p) {
    int now=0;
    for(int i=30; i>=0; --i) {
        int s=p>>i&1;
        if(!node[now][s]) node[now][s]=++cnt;
        now=node[now][s];
    }
}

inline int match(int p) {
    int now=0, ans=0;
    for(int i=30; i>=0; --i) {
        int s=p>>i&1;
        if(node[now][!s]) ans|=1<<i, now=node[now][!s];
        else now=node[now][s];
    }
    return ans;
}

int main() {
    //ios::sync_with_stdio(false); cin.tie(0);
    N=read();
    for(int i=1; i<N; ++i) {
        int u=read(), v=read(), w=read();
        add_edge(u,v,w);
    }
    dfs(1,0);
    insert(a[1]); int ans=0;
    for(int i=2; i<=N; ++i) max(ans,match(a[i])), insert(a[i]);
    cout<<ans<<endl;
}
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务