[NOIP模拟](codevs 1187) Xor

来源:互联网 发布:傲剑洗髓升级数据大全 编辑:程序博客网 时间:2024/06/06 03:39

[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% 的输入数据 :1N100000c2311

题解 & 想法

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

                  这里写图片描述

下面贴出代码 :

#include <cstdio>#include <cstdlib>#include <cstring>#include <string>#include <algorithm>#include <iostream>#include <cmath>#include <ctime>#include <map>#include <vector>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<<ans;}

本题结束 :

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

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

原创粉丝点击