zoukankan      html  css  js  c++  java
  • POJ3764 字典树

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

    题意简单来说就是给你一棵树,从树上找两个点它们之间所有边权的异或值最大。

    假设从根节点到i点的异或值为xor[i],那么从a点到b点的异或值应该是xor[a]^xor[b]吧,因为从根节点到a,b祖先节点会异或掉自身。

    那么我们可以先将树遍历一遍,处理出根节点到每一个点的异或值,然后运用字典树求最大异或二元组的方法得出答案。

    简单说一下如何求最大异或二元组,将每一个点以二进制的形式插入字典树,对于每一个数,沿着它每一位相反的值查找字典树,当然如果字典树没有该节点,就走相同的值的那边,最后异或上查找到的数,就是这个数对应的最大二元组,最后取一个最大值就是答案。

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <list>
    #include <utility>
    #define MAXN 100010
    using namespace std;
    typedef long long LL;
    int n,d[MAXN],tire[32*MAXN][2],tot=1,head[MAXN],cnt=0;
    struct List{
        int v,e,nxt;
    }edge[MAXN*2];
    
    void Dfs(int node,int father)
    {
        for(int i=head[node];i;i=edge[i].nxt)
        {
            int nxt=edge[i].v,len=edge[i].e;
            if(nxt!=father)
            {
                d[nxt]=d[node]^len;
                Dfs(nxt,node);
            }
        }
    }
    
    void Insert(int x)
    {
        int p=1;
        for(int i=31;i>=0;i--)
        {
            int b=(x>>i)&1;
            if(!tire[p][b]) tire[p][b]=++tot,tire[tot][1]=0,tire[tot][0]=0;
            p=tire[p][b];
        }
    }
    
    int Search(int x)
    {
        int p=1,y=0;
        for(int i=31;i>=0;i--)
        {
            int b=!((x>>i)&1);
            if(tire[p][b]) y+=b<<i,p=tire[p][b];
            else y+=(!b)<<i,p=tire[p][!b];
        }
        return x^y;
    }
    
    void connect(int u,int v,int e)
    {
        edge[++cnt].v=v;edge[cnt].e=e;
        edge[cnt].nxt=head[u];head[u]=cnt;
    }
    
    int main()
    {
        while(~scanf("%d",&n))
        {
            tot=1;
            tire[1][0]=0,tire[1][1]=0;
            memset(head,0,sizeof(head));
            cnt=0;
            for(int i=1,u,v,e;i<n;i++)
            {
                scanf("%d%d%d",&u,&v,&e);
                connect(u,v,e);
                connect(v,u,e);
            }
            Dfs(0,0);
            int ans=-1;
            for(int i=0;i<n;i++)
            {
                Insert(d[i]);
                ans=max(ans,Search(d[i]));
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Java中的transient关键字
    【笔记】html的改变(上)
    《开发板 — 实现看门狗》
    《头文件导致Symbol xxx multiply defined重复定义问题分析和解决》
    《APP读取按键值》
    《补充 — Linux内核device结构体分析(转)》
    《设备树LED模板驱动程序》
    《C库 — 字符串和整型数相互转换函数atoi和itoa》
    《Ubuntu — rsync命令》
    《Ubuntu — 2>/dev/null和>/dev/null 2>&1和2>&1>/dev/null的区别》
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/11313489.html
Copyright © 2011-2022 走看看