【01trie树】P4551 最长异或路径

 

//最长异或路径,重点在于01tried树与异或的性质,首先因为异或的性质重复两次异或等于没有 操作也就没有 重复路径的
//顾虑
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define  LL unsigned long long
using namespace std;
const int N = 2e6 + 10;
int  head[N];
struct trie {
    int ch[2];
}t[N];

struct edge {
    int to;
    int w;
    int nxt;
}e[N];
int cnt = -1, sum[N];
inline void add(int u, int v, int w) {//建图
    e[++cnt].to = v;
    e[cnt].w = w;
    e[cnt].nxt = head[u];
    head[u] = cnt;
}


inline void dfs(int u, int fa) {//求到根路径的异或和
    int v, w;
    for (int i = head[u]; ~i; i = e[i].nxt) {
        v = e[i].to;
        w = e[i].w;
        if (v != fa) {
            sum[v] = sum[u] ^ w;
            dfs(v, u);
        }
    }
}
int tot = 0;
inline void build(int n) {

    for (int i = 1; i <= n; i++) {
        bool k;
        for (int j = (1 << 30), p = 0; j; j >>= 1) {
            k = j & sum[i];
            if (!t[p].ch[k]) {
                t[p].ch[k] = ++tot;
            }
            p = t[p].ch[k];
        }
    }
}

int check(int val, int x) {
    int ans = 0;
    bool k;
    for (int i = (1 << 30); i; i >>= 1) {
        k = val & i;//计算该位的01,
        if (t[x].ch[!k]) {//查看所有节点异或和值中在该路线的该位置有没有有值的,并且是不同于val的,这样异或值得该位便是1
            //这里求出的答案中将所有sum的每一位01都铺成一条条01路径,通过对路径的选择最终选择出到底是那一条路径的01值,
            //即哪一个sum,但是从val出发的求出的另一个sum仅仅代表从该val所代表的节点出发所能达到的最大的,因此要
            //将所有节点都当做起点尝试一遍,求出最大值.
            ans += i;
            x = t[x].ch[!k];
        }
        else x = t[x].ch[k];
    }
    return ans;
}
int main() {
    memset(head, -1, sizeof(head));
    int n;
    cin >> n;
    //首先是建图,这里使用链式前向星,
    for (int i = 1, u, v, w; i < n; i++) {
        cin >> u >> v >> w;
        add(u, v, w);//因为是无向图
        add(v, u, w);
    }
    dfs(1, -1);//使用dfs以1号节点为根节点,计算每个节点到根节点的异或路径和值
    build(n);//使用每个节点到根节点的异或和值建立01树
    int ans = 0;//答案.
    for (int i = 1; i <= n; ++i) {
        ans = max(ans, check(sum[i], 0));//遍历从一号节点到根节点的异或和可以得到的最大值
    }
    cout << ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值