POJ3764 The xor-longest Path

题目大意:给定一棵树,每条边都有对应的权值,在树上找一条简单的路径,使得所有边权值的异或值最大。

分析:这个类似于前边写过的一个数组选定两个数的最大异或值,先dfs预处理一下从1到i的异或值D[i],然后当你想要取到s到e的异或值就是D[s]^D[e]。接下来就相当于之前写过的两个数的最大异或值问题。求解最大异或值问题就是利用字典树,就可以高效的解决。

代码:

#include<iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1e5+7;
struct node{
    int u,v,w,nt;
}edge[maxn*4];
int tol;
int head[maxn];
int trie[maxn*32][2];
int tot;
bool vis[maxn];
int D[maxn];
void addEdge(int u,int v,int w){
    edge[tol].u=u;
    edge[tol].v=v;
    edge[tol].w=w;

    edge[tol].nt=head[u];
    head[u]=tol++;
}
void init(int n){
    tot=1;
    tol=0;
    memset(vis,false,sizeof(vis));
    memset(trie,0,sizeof(trie));
    memset(D,0,sizeof(D));
    memset(head,-1,sizeof(head));
}
void dfs(int u){
    vis[u]=true;
    for(int i=head[u];i!=-1;i=edge[i].nt){
        int v=edge[i].v;
        if(vis[v]) continue;
        int w=edge[i].w;
        D[v]=D[u]^w;
        dfs(v);
    }
}
void insert(int x){
    int p=1;
    for(int i=31;i>=0;i--){
        int k=x>>i&1;
        if(!trie[p][k]) trie[p][k]=++tot;
        p=trie[p][k];
    }
}
int search(int x){
    int p=1;
    int ans=0;
    for(int i=31;i>=0;i--){
        int k=x>>i&1;
        if(trie[p][!k])
            ans|=(1<<i),p=trie[p][!k];
        else
            p=trie[p][k];
    }
    return ans;
}
int main(){
    int n,u,v,w;
    while(scanf("%d",&n)!=EOF){
        init(n);
        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);
        int ans=0;
        for(int i=0;i<n;i++){
            ans=max(ans,search(D[i]));
            insert(D[i]);
        }
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/SwiftAC/p/12153114.html