POJ3764:The xor-longest Path

来源:互联网 发布:淘宝直播有什么要求 编辑:程序博客网 时间:2024/05/30 23:11

题目链接

http://poj.org/problem?id=3764

解题要点

  1. 树结构内任意两点u,v间的路径权值异或和f(u,v),具有如下性质

    f(u,v)=f(root,u)xorf(root,v)

    其中,root是根结点。

  2. 找到所有节点与root的路径权值异或和f(root,i),iVV表示节点集合。将异或和(32位整形int)存入到Trie树。

  3. 遍历2中所有异或和,力求在Trie树中寻找到与其异或结果最大的值。

具体原因请看:
http://blog.csdn.net/u010232171/article/details/49685523
补充知识点:
1. 树的表示方法
除过矩阵和链表法(这里指使用指针或者vector容器的方法)外,可以使用数组表示,名称是前插表示法。好处是多次运算时,不需要为了建立树,重复开辟和收回空间。因此,时间开销也会降低。
2.固定规模的问题,可以事先开辟好足够空间,以减少操作(new,delete)等带来的时间开销。

#include <iostream>using namespace std;// 固定Trie树高度const int TrieHigh = 31;//Tree节点数const int MAX_N = 100002;//根结点到其余N-1个节点的路径异或和,以及索引int pathXor[MAX_N], paths;/*基于前插表法的树(tree)结构,所有边都是有向的*/ //记录与节点相关的边编号int head[MAX_N];//边结构:指向点序号,权值,下一条边序号struct Edge{    int v;    int w;    int next;}edge[2*MAX_N];//插入新边(u->v)到u的链表(用数组表示链表)void addEdge(int u, int v, int w, int id){    edge[id].v = v;    edge[id].w = w;    edge[id].next = head[u];    head[u] = id;    return;}void buildTree(int N){    int u, v, w;    for(int i = 0; i < N-1; ++i){        scanf("%d%d%d", &u, &v, &w);        addEdge(u, v, w, i);        addEdge(v, u, w, i+N-1);    }    return;}/*建立Trie树:* 提前分配好树节点*///资源序号int idTrie;//树节点定义struct TrieNode{    int value;    int next[2];}trie[TrieHigh*MAX_N];//Trie树插入新节点void insert(int val){    int root(0), bit;    for(int i = TrieHigh-1; i >= 0; --i){        bit = ((val & (1<<i)) != 0);        if( trie[root].next[bit] == -1 ){            trie[idTrie].next[0] = trie[idTrie].next[1] = -1;            trie[root].next[bit] = idTrie++;        }        root = trie[root].next[bit];    }    trie[root].value = val;    return;}//返回值是与val异或结果最大的值int query(int val){    int root(0), bit;    for(int i = TrieHigh-1; i >= 0; --i){        bit = ((val & (1<<i)) != 0);        root = (trie[root].next[1-bit] != -1) ? trie[root].next[1-bit]: root = trie[root].next[bit];    }    return trie[root].value;}//初始化所有内存void init(){        memset(head, -1, sizeof(head));    paths = 0;    trie[0].next[0] = trie[0].next[1] = -1;    idTrie = 1;    return;}//深度优先,找到所有从根结点出发路径的异或和void dfs(int root, int parent, int len){    int id(head[root]), lenXor;    while( id != -1 ){        if( edge[id].v != parent ){            lenXor = len^edge[id].w;            insert(lenXor);            pathXor[paths++] = lenXor;            dfs( edge[id].v, root, lenXor );        }        id = edge[id].next;    }    return;}int main(){    int N;    while( scanf("%d", &N) == 1 ){        init();        buildTree(N);        dfs(0, -1, 0);        int res(0);        for(int i = 0; i < paths; ++i){            res = max(res, pathXor[i]);            res = max(res, pathXor[i]^query(pathXor[i]));        }        printf("%d\n", res);    }    return 0;}
0 0