POJ 3764 The xor-longest Path(字典树 + 贪心)

来源:互联网 发布:mysql忘记密码 编辑:程序博客网 时间:2024/04/29 15:43

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


题意:给出一棵N个点的树,定义两点间的异或权值为这两点间的所有边权的异或值,求树中最大的两点异或权值


思路:对于异或有性质 A ^ C = (A ^ B) ^ (B ^ C),故而树上两点A, C的异或值可以通过与两点分别于根节点的异或值再异或得到,这样可以先预处理出所有点到根节点的异或值,然后考虑这N个值如何选出两个值异或值最大,可以将每个值从高位到低位拆成二进制的串插入字典树,每当插入完成后就在字典树上进行遍历,因为是从高位到低位,所以每次应保证高位的值尽量能取到,所以每次尽量找与当前位相反的结点进行遍历



#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <utility>#include <cmath>#include <queue>#include <set>#include <map>#include <climits>#include <functional>#include <deque>#include <ctime>#include <string>#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int maxn = 100010;const int maxm = 6000010;int cnt, head[maxn], dis[maxn];struct Edge{    int to, w, next;} edge[maxn << 1];void init(){    cnt = 0;    memset(head, -1, sizeof(head));}void addedge(int u, int v, int w){    edge[cnt].to = v;    edge[cnt].w = w;    edge[cnt].next = head[u];    head[u] = cnt++;}void dfs(int u, int fa, int w){    dis[u] = w;    for (int i = head[u]; ~i; i = edge[i].next)    {        int v = edge[i].to;        if (v == fa) continue;        dfs(v, u, w ^ edge[i].w);    }}struct Trie{    int ch[maxm][2];    int sz;    void init()    {        sz = 1;        memset(ch[0], 0, sizeof(ch[0]));    }    void insert(int num)    {        int u = 0;        for (int i = 30; i >= 0; i--)        {            int w;            if (num & (1 << i))                w = 1;            else                w = 0;            if (!ch[u][w])            {                memset(ch[sz], 0, sizeof(ch[sz]));                ch[u][w] = sz++;            }            u = ch[u][w];        }    }    int query(int num)    {        int u = 0, res = 0;        for (int i = 30; i >= 0; i--)        {            int w;            if (num & (1 << i))                w = 1;            else                w = 0;            if (ch[u][w ^ 1])            {                u = ch[u][w ^ 1];                res *= 2;                res += 1;            }            else            {                u = ch[u][w];                res *= 2;            }        }        return res;    }} tr;int main(){    int n;    while (~scanf("%d", &n))    {        init();        for (int i = 0; i < n - 1; i++)        {            int u, v, w;            scanf("%d%d%d", &u, &v, &w);            addedge(u, v, w);            addedge(v, u, w);        }        dfs(0, -1, 0);        // for (int i = 0; i < n; i++)        //     printf("%d ", dis[i]);        tr.init();        int ans = 0;        for (int i = 0; i < n; i++)        {            tr.insert(dis[i]);            ans = max(ans, tr.query(dis[i]));        }        cout << ans << endl;    }    return 0;}


0 0