zoukankan      html  css  js  c++  java
  • ACM学习历程—POJ 3764 The xor-longest Path(xor && 字典树 && 贪心)

    题目链接:http://poj.org/problem?id=3764

    题目大意是在树上求一条路径,使得xor和最大。

    由于是在树上,所以两个结点之间应有唯一路径。

    xor(u, v) = xor(0, u)^xor(0, v)

    所以如果预处理出0结点到所有结点的xor路径和,问题就转换成了求n个数中取出两个数,使得xor最大。

    这个之前用字典树处理过类似问题。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #define LL long long
    
    using namespace std;
    
    const int maxN = 100005;
    
    //求n个数中取出两个数能xor的最大值
    //Trie Tree字典树
    //len*n, len为数的二进制最大长度
    const int len = 31;//len表示数的二进制最大长度
    struct Trie
    {
        int next[2];
    }tree[maxN*len];
    int cntTree;
    
    void initTree()
    {
        cntTree = 0;
        memset(tree, -1, sizeof(tree));
    }
    
    void add(int x)
    {
        int now = 0;
        bool k;
        for (int i = len; i >= 0; i--)
        {
            k = x&(1<<i);
            if (tree[now].next[k] == -1)
                tree[now].next[k] = ++cntTree;
            now = tree[now].next[k];
        }
    }
    
    //返回当前数中能和x合成最大数的数
    int query(int x)
    {
        int v = 0, now = 0;
        bool k;
        for (int i = len; i >= 0; i--)
        {
            k = x&(1<<i);
            if (tree[now].next[!k] != -1)
                k = !k;
            v = v|(k<<i);
            now = tree[now].next[k];
        }
        return v;
    }
    
    //链式前向星
    struct Edge
    {
        int to, next;
        int val;
    }edge[maxN*2];
    
    int head[maxN], cnt;
    
    void addEdge(int u, int v, int w)
    {
        edge[cnt].to = v;
        edge[cnt].next = head[u];
        edge[cnt].val = w;
        head[u] = cnt;
        cnt++;
    }
    
    void initEdge()
    {
        memset(head, -1, sizeof(head));
        cnt = 0;
    }
    
    int n, p[maxN];
    
    void dfs(int now)
    {
        int to;
        for (int i = head[now]; i != -1; i = edge[i].next)
        {
            to = edge[i].to;
            if (p[to] == -1)
            {
                p[to] = p[now]^edge[i].val;
                dfs(to);
            }
        }
    }
    
    void input()
    {
        initEdge();
        memset(p, -1, sizeof(p));
        int u, v, w;
        for (int i = 1; i < n; ++i)
        {
            scanf("%d%d%d", &u, &v, &w);
            addEdge(u, v, w);
            addEdge(v, u, w);
        }
        p[0] = 0;
        dfs(0);
    }
    
    void work()
    {
        int ans = 0;
        initTree();
        for (int i = 0; i < n; ++i)
        {
            add(p[i]);
            ans = max(ans, p[i]^query(p[i]));
        }
        printf("%d
    ", ans);
    }
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        while (scanf("%d", &n) != EOF)
        {
            input();
            work();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    用Chrome和android SDK远程调试移动端页面
    如何配置能让fiddler抓去https的请求?
    开源免费的简易中文分词系统SCWS – PHP版
    Node.js 开发环境搭建及设置
    linux 安装 git server
    linux下 删除乱码文件名
    PowerDesigner 使用问题
    linux 设置开机大全
    mysql 实现 row_number() over(pattition by a order by b )
    WebApi Filter 中断返回字符串信息
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/4957266.html
Copyright © 2011-2022 走看看