[NOIP模拟](codevs 1187) Xor

[NOIP模拟](codevs 1187) Xor


题目背景

OURCE:NOIP2015-SHY-7
CODEVS 1187 : 这里是链接

题目描述

    求一棵带边权的树的一条最大 Xor 路径的值。这里的“路径”不一定从根到叶子结点,中间一段路径只要满足条件也可以。

输入格式

    第一行,一个整数 N ,表示一颗树有 N 个节点,接下来 N - 1 行,每行三个整数 a, b, c 表示节点 a 和节点 b 之间有条权值为 c 的边。

输出格式

输出仅一行,即所求的最大值。

样例数据

Input

4
1 2 3
1 3 4
1 4 7

Output

7

备注

【数据范围】
  对 40% 的输入数据 :数据退化为一条链;
 另对 10% 的输入数据 : N1000
 对 100% 的输入数据 : 1N100000 c2311

题解 & 想法

    这道题居然是个套路题,唉, 都怪自己做题太少了,而且直接输出最大值可以得 45 分, 早知道自己就骗分了。
正题 :
    这道题很明显适合二进制有关(废话), 我们考虑如何表示一条路径, 我们令 dis[x] 表示从根节点到 x 节点的路径异或值, 那么从 x 到 y 的路径我们可以表示成 : dis[x] ^ dis[y], 因为从根节点到这两个节点的共同路径异或起来都为 0, 所以这个式子显然成立。
    然后我们考虑对于一个 x 如何去找与之异或起来异或最大的 y, 这时候我们就可以建一颗 trie 树, insert 时从最高位跑到最低位, 寻找答案时,直接寻找与当前二进制位异或起来为 1 的点, 是一个贪心的思想, 毕竟当前为 1 一定比后面为 1 大。如果没有只有走异或为零的点。
                  [NOIP模拟](codevs 1187) Xor_第1张图片

                  [NOIP模拟](codevs 1187) Xor_第2张图片

下面贴出代码 :

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

inline int read() {
    int i = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1; ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        i = (i << 3) + (i << 1) + ch - '0'; ch = getchar();
    }
    return i * f;
}

const int MAXN = 1e5 + 5;
int first[MAXN], to[MAXN * 2], nxt[MAXN * 2], len[MAXN * 2];
int tot, dis[MAXN], maxx, cnt, vis[MAXN];
struct point {
    int son[2];
};
point tr[MAXN * 31];

inline void addedge(int x, int y, int z) {
    nxt[++tot] = first[x]; first[x] = tot; to[tot] = y; len[tot] = z;
    nxt[++tot] = first[y]; first[y] = tot; to[tot] = x; len[tot] = z;
}

inline void dfs(int x) {
    vis[x] = 1;
    for(int i = first[x]; i; i = nxt[i]) {
        int y = to[i];
        dis[y] = dis[x] ^ len[i];
        if(!vis[y]) dfs(y);
    }
}

inline void insert(int x) {
    int u = 0;
    for(int i = maxx; i >= 0; --i) {
        int t = (x >> i) & 1;
        if(!tr[u].son[t]) tr[u].son[t] = ++cnt;
        u = tr[u].son[t];
    }
}

inline int solve(int x) {
    int u = 0, ans = 0;
    for(int i = maxx; i >= 0; --i) {
        int t = (x >> i) & 1;
        if(!tr[u].son[t ^ 1]) ans += (t & 1) << i, u = tr[u].son[t & 1];
        else ans += (t ^ 1) << i, u = tr[u].son[t ^ 1]; 
    }
    return ans ^ x;
}

int main() {
    int n = read();
    for(int i = 1; i <= n - 1; ++i) {
        int x = read(), y = read(), z = read();
        addedge(x, y, z); maxx = max(maxx, z);
    }
    int k = 0; while(maxx) { maxx >>= 1, ++k; } maxx = k;
    dfs(1);
    for(int i = 2; i <= n; ++i) insert(dis[i]);
    int ans = 0;
    for(int i = 2; i <= n; ++i) {
        int now = solve(dis[i]);
        ans = max(ans, now);
    }
    cout<

本题结束 :

感谢阅读本篇文章,喜欢的话,点个赞吧,你的鼓励就是我最大的动力

有什么意见,尽情发表吧。

你可能感兴趣的:(NOIP模拟,trie树)