poj 3764

来源:互联网 发布:知乎电脑配件专家 编辑:程序博客网 时间:2024/04/29 11:37

题意:已知:给出n个结点,n-1条边(附边的长度).定义:两结点间的异或长度为两点之间所有边相异或的值.求:树中的最长异或长度.
思路:恒等式:x ^ y == ( x ^ z ) ^ ( y ^ z ),有了这个等式,我们可以将任意两点x、y的异或长度Xor[x,y]转化为x到另一结点z(如z=0)的异或长度Xor[x,z],y到另一结点z(如z=0)的异或长度Xor[y,z]相异或,即Xor[x,y]=Xor[x,z] ^ Xor[y,z]。这样一来,得求出所有结点到z的异或长度,可用DFS来完成这一步。
下一步是要求任意两个结点到z的异或长度相异或的值中的最大值,如果单纯用两个for循环的话,由于n最大可达100000,不用说一定会超时。可以将这些结点存入字典树中,然后来查找,这样的话时间复杂度为O( n*log2( Max(Xor[i,z]) ) )=O(n*30),0<=i

#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>#include <stdlib.h>using namespace std;#define MAXN 100100struct Edge{   int to, next, w;}E[MAXN << 1];int head[MAXN], ecnt;bool vis[MAXN];int val[MAXN];void init(){    memset(vis, false, sizeof(vis));    memset(head, -1, sizeof(head));    ecnt = 0;}void Addedge( int u, int v, int w){    E[ecnt].to = v;    E[ecnt].w = w;    E[ecnt].next = head[u];    head[u] = ecnt++;}void dfs(int u, int cur){    vis[u] = true;    val[u] = cur;    for( int i = head[u]; i != -1; i = E[i].next)    {        if(!vis[E[i].to])          dfs(E[i].to, cur^E[i].w);    }}struct Node{   int next[2];}Tire[MAXN*60];int Tlen;void insert(int val){    int root = 0;    for( int i = 30; i >= 0; i --)    {        int cur = ((val&(1 << i)) ? 1 : 0);        if(!Tire[root].next[cur])        {            Tire[root].next[cur] = ++Tlen;            Tire[Tlen].next[0] = Tire[Tlen].next[1] = 0;        }        root = Tire[root].next[cur];    }}int find(int val){    int root = 0, res = 0;    for( int i = 30; i >= 0; i--)    {        int cur = ((val&(1<<i))? 0 : 1);        if(Tire[root].next[cur])        {              res |= (1 << i);              root = Tire[root].next[cur];        }        else root = Tire[root].next[!cur];    }    return res;}int main(){    int n;    while(scanf("%d",&n) != EOF && n)    {        int u, v, w;        init();        for( int i = 0; i < n - 1; i++)        {            scanf("%d%d%d",&u, &v, &w);            Addedge(u, v, w);            Addedge(v, u, w);        }        dfs(0, 0);        Tire[0].next[0] = Tire[0].next[1] = 0;        Tlen = 0;        int ans = 0;        for( int i = 0; i < n; i++)        {            insert(val[i]);            int w = find(val[i]);            if(ans < w)             ans = w;        }        printf("%d\n",ans);    }    return 0;}
0 0