【Trie树】POJ 3764 最大连续异或和

【Trie树】POJ 3764 最大连续异或和

题意

已知:给出n个结点的树,定义两结点间的权值为两点之间所有边相异或的值。
求:树中的某两点间的最大权值。

解法

是道好题,在做HDU5845,发现Trie树解决连续异或和问题是很有趣的套路,遂找到这题学习。
//TODO

代码

POJ 数据范围有坑,TLE半天,点开Discuss发现数据范围可能是200000。

//Trie树求最大/最小连续异或和
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int MAXN = 2e5 + 6;
const int MAXBIT = 30;
struct edge
{
    int nx, v, w;
}e[MAXN << 1];
int last[MAXN];
int etot;
int n;

struct Trie
{
    int child[2];
    void init()
    {
        child[1] = child[0] = -1;
    }
}tr[MAXN << 5];
int cnt;
bool vis[MAXN];
int XOR[MAXN];

void add_edge(int u, int v, int w)
{
    e[etot].nx = last[u];
    e[etot].v = v;
    e[etot].w = w;
    last[u] = etot++;
    e[etot].nx = last[v];
    e[etot].v = u;
    e[etot].w = w;
    last[v] = etot++;
}

void Insert(int x)
{
    int cur = 0;
    for (int i = MAXBIT; i >= 0; --i)
    {
        int k = (x >> i) & 1;
        if (tr[cur].child[k] == -1)
        {
            tr[cur].child[k] = ++cnt;
            tr[cnt].init();
        }
        cur = tr[cur].child[k];
    }
}

int Find(int x)
{
    int cur = 0;
    int ans = 0;
    for (int i = MAXBIT; i >= 0; --i)
    {
        int k = ((x >> i) & 1)? 0 : 1;
        if (tr[cur].child[k] != -1)
        {
            ans |= (1 << i);
            cur = tr[cur].child[k];
        }
        else
            cur = tr[cur].child[1 - k];
    }
    return ans;
}

void dfs(int u)
{
    //Insert(XOR[u]);
    vis[u] = 1;
    for(int k = last[u]; k != -1; k = e[k].nx)
    {
        if (vis[e[k].v]) continue;
        else XOR[e[k].v] = XOR[u] ^ e[k].w;
        dfs(e[k].v);
    }
}

void init()
{
    etot = 0;
    //memset(last, 0xFF, sizeof(last));
    cnt = 0;
    tr[0].init();
    for(int i = 0; i < n; ++i)
    {
        last[i] = -1;
        vis[i] = XOR[i] = 0;
    }
    //memset(vis, 0, sizeof(vis));
    //memset(XOR, 0, sizeof(XOR));
}

int main()
{
    int ans, u, v, w;
    //while(cin>>n)
    while(scanf("%d", &n) == 1)
    {
        init();
        for (int i = 1; i < n; ++i)
        {
            scanf("%d%d%d", &u, &v, &w);
            //cin>>u>>v>>w;
            add_edge(u,v,w);
        }
        dfs(0);
        ans = -1;
        for (int i = 0; i < n; ++i)
        {
            Insert(XOR[i]);
            int t = Find(XOR[i]);
            ans = max(ans, t);
        }
        printf("%d\n", ans);
        //cout<<ans<<endl;
    }

    return 0;
}

参考

http://codecloud.net/86072.html
https://problemsolvingnotes.wordpress.com/2012/02/22/poj-3764-the-xor-longest-path/

    原文作者:Trie树
    原文地址: https://blog.csdn.net/iSerendipity/article/details/65937503
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注