POJ 3764 The xor-longest Path (字典树求最大异或 + 链式前向星存图)

The xor-longest Path

题目大意:给定一颗N个节点的树,树上的每一条边都有一个权值。从数中选择两个点x和y,把从x到y的路径上的所有边权xor(异或)起来,得到的结果最大是多少?

解题思路:

因为 a ^ b==(a ^ c) ^ (b ^ c), 即两个点到根的异或和异或一下就是这两个点之间的异或和,根据这条性质,我们可以从根节点(也就是前文中的 C )开始跑一遍 dfs 记录下当前节点到根节点的异或和,然后转成01串插入到trie树里面,最后按照贪心思想匹配的时候尽可能的匹配与当前位不同的即可。

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int MAXN = 100100;
int t[MAXN*33][3],tot = 1,D[MAXN];
int head[MAXN],cnt = 1;
bool vis[MAXN];
//因为用vector会超时,所以我们采用数组来存贮树结构,儿子+兄弟们  ----> 链式前向星
struct Edge{
    int to,val,brh;
    Edge(){}
    Edge(int to,int val,int brh):to(to),val(val),brh(brh){}
}edges[MAXN*4];

void addEdge(int from,int to,int val){                 //无向边建图
    edges[cnt] = Edge(to,val,head[from]);
    head[from] = cnt++;
}

void init(){
    memset(head,-1,sizeof head);
    memset(vis,false,sizeof vis);
    memset(t,0,sizeof t);
    memset(D,0,sizeof D);
    cnt = tot = 1;
}

void dfs(int p,int ww){                         //记录当前节点到根节点的异或和
    vis[p] = true;
    D[p] = ww;
    for(int i = head[p];i != -1;i = edges[i].brh){
        if(!vis[edges[i].to]) 
            dfs(edges[i].to,ww^edges[i].val);
    }
}

void insert(int x){                         //插入到字典树
    int p = 1;
    for(int k = 30;k >= 0;k--){               //转换成01串
        int ch = x>>k&1;                      // if(x&(1<<i)) ch=1; else ch=0;
        if(t[p][ch]==0){
        	t[p][ch]=++tot;
		} 
        p = t[p][ch];
    }
}

int search(int x){
    int p = 1,ans = 0;
    for(int k = 30;k >= 0;k--){
        int ch = x>>k&1;
        if(t[p][!ch]){                     //尽可能找不一样的,贪心思想
            p = t[p][!ch];
            ans |= 1<<k;
        }else p = t[p][ch];
    }
    return ans;
}


int main(){
    int n,u,v,w,ans;
    while(~scanf("%d",&n)){
        ans=0;
		init();
        for(int i =1;i<n;i++){
            scanf("%d%d%d",&u,&v,&w);
            addEdge(u,v,w);
            addEdge(v,u,w);
        }
        dfs(0,0);
        for(int i=0;i<n;i++) insert(D[i]);
        for(int i=0;i<n;i++) ans=max(ans,search(D[i]));
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43872264/article/details/107646783