Luogu P4551 最长异或路径

版权声明:欢迎转载 https://blog.csdn.net/yandaoqiusheng/article/details/89279966

题目链接:传送门
在树中找两个节点使他们的异或路径最大

01trie是个好东西
比如今年十二省联考的day1 t1,加个可持久化而已
跟普通trie相比就是每个节点存的是二进制0或1
从根到一个节点的二进制连起来存的就是一个数字
这样可以让你在树上贪心
因为深度越大的节点若为1则这个值一定更大
比如8(1000)> 7(111)
对于这个题
处理出根节点到每个节点的异或
挨个插入到01trie中
遍历每个节点求最大值
看代码还是很好理解的

/**
 * @Date:   2019-04-11T19:24:10+08:00
 * @Last modified time: 2019-04-13T10:33:57+08:00
 */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <complex>
#include <algorithm>
#include <climits>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define A 2000010
#define B 2010

using namespace std;
typedef long long ll;
struct node {
    int next, to, w;
}e[A];
int head[A], num;
void add(int fr, int to, int w) {
    e[++num].next = head[fr];
    e[num].to = to;
    e[num].w = w;
    head[fr] = num;
}
int ch[A][2], n, a, b, c, cnt = 1;
ll s[A];
void dfs(int fr, int faa) {
    for (int i = head[fr]; i; i = e[i].next) {
        int ca = e[i].to;
        if (ca == faa) continue;
        s[ca] = s[fr] ^ e[i].w;
        dfs(ca, fr);
    }
}
void insert(ll x, int fr = 1) {
    for (int i = 32; i >= 0; i--) {
        int pos = (x >> i) & 1; //x的从右数第i位是0还是1
        if (!ch[fr][pos]) ch[fr][pos] = ++cnt;
        fr = ch[fr][pos];
    }
}
ll ask(ll x, int fr = 1, ll ans = 0) {
    for (int i = 32; i >= 0; i--) {
        int pos = (x >> i) & 1; //选择对应位不同的继续走
        if (ch[fr][pos ^ 1]) ans += 1LL << i, fr = ch[fr][pos ^ 1];
        else fr = ch[fr][pos];
    }
    return ans;
}

int main(int argc, char const *argv[]) {
	cin >> n;
    for (int i = 1; i < n; i++) cin >> a >> b >> c, add(a, b, c), add(b, a, c);
    dfs(1, 0); ll ans = 0;
    for (int i = 1; i <= n; i++) insert(s[i]);
    for (int i = 1; i <= n; i++) ans = max(ans, ask(s[i]));
    cout << ans << endl;
}

猜你喜欢

转载自blog.csdn.net/yandaoqiusheng/article/details/89279966