【Trie】POJ 3764 The xor-longest Path

链接

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

大意

给定 n 个点和 m 条无向边
设一种运算 a + b ,表示从 a b 的路径长度的异或值,求出最大的 a + b

思路

D [ x ] 表示根节点到 x 的路径上所有边权的 x o r 值,设 y x 的子节点,显然有

D [ y ] = D [ x ]   x o r   W e i g h t ( x , y )

所以我们可以先用一个 b f s 或者 d f s (本人用的是 b f s )求出所有的 D [ i ] ,然后通过发现 x y 的路径的异或值就等于 D [ x ]   x o r   D [ y ] ,这是因为根据 x o r 的性质, a   x o r   a = 0 x 到根和 y 到跟这两条路径重叠的部分恰好被抵消掉
所以,问题就变成了从 D 数组中任选两个数,使得它们的异或值最大,即为CH 1602 The XOR Largest Pair

代码

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int trie[3500001][2],tot,n,l[200001],cnt,x,y;
long long d[200001],ans,w;
struct node
{
    int next,to;long long w;
}e[200001];
inline void add(register int x,register int y,register long long w)//建边
{
    e[++cnt]=(node){l[x],y,w};l[x]=cnt;
    return;
}
inline void bfs(register int st)//求d
{
    queue<int>q;q.push(st);
    bool vis[1000001]={0};vis[st]=true;
    while(q.size())
    {
        int x=q.front();q.pop();vis[x]=true;
        for(register int i=l[x];~i;i=e[i].next)
        {
            int y=e[i].to,w=e[i].w;
            if(!vis[y])
            {
                q.push(y);
                d[y]=d[x]^w;
            }
        }
    }
    return;
}
inline void insert(register long long x)//插入
{
    int p=0;
    for(register int k=31;k>=0;k--)
    {
        int id=(x>>k)&1;
        if(!trie[p][id]) trie[p][id]=++tot;
        p=trie[p][id];
    }
    return;
}
inline long long search(register long long x)//查找
{
    int p=0;
    long long ans=0;
    for(register int k=31;k>=0;k--)
    {
        int id=(x>>k)&1,o=id^1;
        if(trie[p][o]) {p=trie[p][o];ans=ans<<1|1;}
        else if(trie[p][id]) {p=trie[p][id];ans<<=1;}
    }
    return ans;
}
signed main()
{
    while (~scanf("%d",&n))
    {
        tot=0;cnt=0;
        memset(l,-1,sizeof(l));
        memset(trie,0,sizeof(trie));ans=0;
        memset(d,0,sizeof(d));//初始化
        for(register int i=1;i<n;i++)
        {
            scanf("%d%d%lld",&x,&y,&w);
            x++;y++;
            add(x,y,w);add(y,x,w);//无向边
        }
        bfs(1);//计算d
        for(register int i=1;i<=n;i++)
        {
            ans=max(ans,search(d[i]));
            insert(d[i]);
        }
        printf("%lld\n",ans);//输出
    }
}

猜你喜欢

转载自blog.csdn.net/xuxiayang/article/details/81778442