POJ 3764 - The xor-longest Path - [DFS+字典树变形]

题目链接:http://poj.org/problem?id=3764

Time Limit: 2000MS  Memory Limit: 65536K

Description

In an edge-weighted tree, the xor-length of a path p is defined as the xor sum of the weights of edges on p:

$_{xor}length(p) = \bigoplus_{e \in p}w(e)$

$\oplus$ is the xor operator.

We say a path the xor-longest path if it has the largest xor-length. Given an edge-weighted tree with n nodes, can you find the xor-longest path?  

Input

The input contains several test cases. The first line of each test case contains an integer n(1<=n<=100000), The following n-1 lines each contains three integers u(0 <= u < n),v(0 <= v < n),w(0 <= w < 2^31), which means there is an edge between node u and v of length w.

Output

For each test case output the xor-length of the xor-longest path.

Sample Input

4
0 1 3
1 2 4
1 3 6

Sample Output

7

Hint

The xor-longest path is 0->1->2, which has length $7 = 3 \oplus 4$

题意:

对一棵带权树,我们定义树上的某条路径 $p$ 的“异或长度”为该路径上所有边的边权的异或值。要求你找出树上“异或长度”最长的路径,并求出其“异或长度”。

题解:

显然对于树上任意节点 $x$,我们可以用DFS递推地求出 $dist[x] = dist[par[x]] \oplus w(par[x],x)$。

我们可以枚举所有路径的两个端点 $x,y$,其路径为 $x \sim LCA(x,y) \sim y$。

那么根据异或的性质,就有 $_{xor}length(x \sim y) = dist[x] \oplus dist[y]$,因为 $_{xor}length(root \sim LCA(x,y))$ 这一段同时出现在 $dist[x]$ 和 $dist[y]$ 中,异或之后即为 $0$,正好抵消掉了。

因此,问题就转化为对于长度为 $n$ 的序列 $dist[1] \sim dist[n]$,寻找某一对 $(x,y)$ 使得 $dist[x] \oplus dist[y]$ 最大,给出最大值。该问题即CH 1602 - The XOR Largest Pair - [字典树变形]

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e5+10;

int n;

struct Edge{
    int u,v,w;
    int next;
};
Edge E[2*maxn];
int head[maxn],ne;
void init()
{
    ne=0;
    memset(head,0,sizeof(head));
}
void addedge(int u,int v,int w)
{
    ++ne;
    E[ne].u=u, E[ne].v=v, E[ne].w=w;
    E[ne].next=head[u];
    head[u]=ne;
}

int d[maxn];
bool vis[maxn];
void dfs(int u)
{
    vis[u]=1;
    for(int i=head[u];i;i=E[i].next)
    {
        if(!vis[E[i].v])
        {
            d[E[i].v]=d[u]^E[i].w;
            dfs(E[i].v);
        }
    }
}

namespace Trie
{
    const int SIZE=maxn*32;
    int sz;
    struct TrieNode
    {
        int ed;
        int nxt[2];
    }trie[SIZE];
    void init()
    {
        sz=1;
        memset(trie,0,sizeof(trie));
    }
    void insert(int x)
    {
        int p=1;
        for(int k=30;k>=0;k--)
        {
            int ch=(x>>k)&1;
            if(trie[p].nxt[ch]==0) trie[p].nxt[ch]=++sz;
            p=trie[p].nxt[ch];
        }
    }
    int MaxXor(int x)
    {
        int res=0;
        int p=1;
        for(int k=30;k>=0;k--)
        {
            int ch=(x>>k)&1;
            if(trie[p].nxt[ch^1])
            {
                p=trie[p].nxt[ch^1];
                res|=1<<k;
            }
            else p=trie[p].nxt[ch];
        }
        return res;
    }
};

int main()
{
    while(cin>>n)
    {
        init();
        for(int i=1,u,v,w;i<n;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            addedge(u+1,v+1,w);
            addedge(v+1,u+1,w);
        }

        memset(vis,0,sizeof(vis));
        memset(d,0,sizeof(d));
        dfs(1);

        Trie::init();
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            Trie::insert(d[i]);
            ans=max(ans,Trie::MaxXor(d[i]));
        }
        cout<<ans<<endl;
    }
}

原文地址:https://www.cnblogs.com/dilthey/p/9932409.html

时间: 2024-08-03 22:00:20

POJ 3764 - The xor-longest Path - [DFS+字典树变形]的相关文章

2014百度之星资格赛—— Xor Sum(01字典树)

Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) Total Submission(s): 0    Accepted Submission(s): 0 Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起

hdu-(1298手机相关 dfs+字典树)

题目大意: 在以前,手机输入法很麻烦,因为只有9个键,而字母有26个,所以一个键上同时包含这几个字母,这样的话,为了打出一个字母可能要按几次.比如键5有"JKL", 如果要输入K,那么就要连按两次. 这样的输入法很麻烦.所以一家公司发明了T9技术输入法.这种输入法内置这很多英语单词,它可以根据英语出现的频率,是否存在等信息,每个字母只要按一次,就可以有想要的预选单词. 例如,假设输入法只内置了一个单词"hell", 那么只需要按4355便可以出来. 注意,如果有一个

poj 2513 Colored Sticks 并查集 字典树 欧拉回路判断

点击打开链接题目链接 Colored Sticks Time Limit: 5000MS   Memory Limit: 128000K Total Submissions: 30273   Accepted: 8002 Description You are given a bunch of wooden sticks. Each endpoint of each stick is colored with some color. Is it possible to align the sti

POJ 2513 Colored Sticks(欧拉回路,字典树,并查集)

题意:给定一些木棒,木棒两端都涂上颜色,求是否能将木棒首尾相接,连成一条直线,要求不同木棒相接的一边必须是相同颜色的. 转:kuangbing 无向图存在欧拉路的充要条件为: ①     图是连通的: ②     所有节点的度为偶数,或者有且只有两个度为奇数的节点. 图的连通可以利用并查集去判断. 度数的统计比较容易. view code//第一次用指针写trie,本来是用二维数组,发现数组开不下,只好删删改改,改成指针 //做这道题,知道了欧拉回路判定,还有用指针写trie #include

CODEVS1187 Xor最大路径 (字典树)

由于权值是在边上,所以很容易发现一个性质:d(x,y)=d(x,root) xor d(y,root). 因为有了这个性质,那么就很好做了.对于每一个点统计到root的距离,记为f 数组. 将f数组里的每个值插进按照二进制位插进字典树里面. 枚举每一个点,然后在字典树中搜索最大的xor值就可以了. Program CODEVS1187; const maxn=100008; type arr=record u,v,w,next:int64; end; type arr1=record next:

hdu 1979 DFS + 字典树剪枝

http://acm.hdu.edu.cn/showproblem.php?pid=1979 Fill the blanks Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 373    Accepted Submission(s): 155 Problem Description There is a matrix of 4*4, yo

hust1350Trie【字典树+dfs || 字典树 + LCA】

大意:告诉你一些字符串 让你组成字典树, 然后定义每个节点到所有叶子节点的距离的和等于改点的value 当根节点只有一个孩子,该根节点也算一个叶子节点 问所有节点的value的最小值 分析: 开始做的时候  就想的是   枚举每个点  然后求它到所有叶子节点的和  求任意两点的最近距离  用公共祖先来求 于是就有了这个算法 需要预处理出来所有的叶子节点 不能单纯的用字典树的flag来记录  例如插入aaa aa a  那么 a  aa aaa 都会被当成叶子节点 对于这里的处理 我是排了一次序

codechef Xor Queries (可持久化字典树)

题目链接:codechef Xor Queries 题意: 题解: 一棵可持久化字典树就行了. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=(a);i<=(b);++i) 3 using namespace std; 4 5 const int N=5e5+7; 6 struct Node{int son[2],cnt;}ch[N*40]; 7 int root[N],cnt,ed,n; 8 9 void ins(int

poj 2503 Babelfish(Map、Hash、字典树)

题目链接:http://poj.org/bbs?problem_id=2503 思路分析: 题目数据数据量为10^5, 为查找问题,使用Hash或Map等查找树可以解决,也可以使用字典树查找. 代码(Map实现): #include <iostream> #include <sstream> #include <string> #include <map> using namespace std; int main() { char word[15], fo