zoukankan      html  css  js  c++  java
  • poj3764

      题意就是给一棵树,然后让你求最大的路经异或和是多少,一条路径的异或和是该路径上的边对应的边权的异或和。

      因为^具有自反性,即a^a=0,所以我们只需要dfs处理出根节点到每个点的路径的异或和dp[i],那么u至v的路径的异或和即等于       dp[u]^dp[v],然后把dp[i]都放入01字典树里,枚举起点i,求与dp[i]异或得到的最大的数,然后取最大值即可。

    #include<stdio.h>
    #include<iostream>
    #include<vector>
    using namespace std;
    const int maxn=1e5+10;
    struct node
    {
        int val,cnt,son[2];
        void reset()
        {
            val=cnt=son[0]=son[1]=0;
        }
    }tree[maxn*32];
    struct edge
    {
        int v,w,nxt;
        edge(int v=0,int w=0,int nxt=0)
        {
            this->v=v;
            this->w=w;
            this->nxt=nxt;
        }
    }e[2*maxn];
    int dp[maxn],head[maxn],n,cnt;
    void myinsert(int x)
    {
        int r=0,v;
        for(int i=31;i>=0;i--)
        {
            v=(x>>i)&1;
            if(!tree[r].son[v])
            {
                tree[++cnt].reset();
                tree[r].son[v]=cnt;
            }
            if(r!=0)
                tree[r].cnt++;
            r=tree[r].son[v];
        }
        tree[r].val=x;
        tree[r].cnt++;
    }
    int query(int x)
    {
        int r=0,v;
        for(int i=31;i>=0;i--)
        {
            v=(x>>i)&1;
            if(tree[r].son[v^1]&&tree[tree[r].son[v^1]].cnt)
                r=tree[r].son[v^1];
            else
                r=tree[r].son[v];
        }
        return tree[r].val^x;
    }
    void dfs(int now,int fa)
    {
        int v,w;
        for(int i=head[now];i!=-1;i=e[i].nxt)
        {
            v=e[i].v;
            w=e[i].w;
            if(v==fa) continue;
            dp[v]=dp[now]^w;
            dfs(v,now);
        }
    }
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
        return x*f;
    }
    int main()
    {
        int maxx;
        while(scanf("%d",&n)!=EOF)
        {
    
            tree[0].reset();
            cnt=0;
            maxx=0;
            for(int i=0;i<n;i++) head[i]=-1;
            for(int i=1,cnt=0;i<n;i++)
            {
                int u,v,w;
                u=read();
                v=read();
                w=read();
                e[cnt]=edge(v,w,head[u]);
                head[u]=cnt++;
                e[cnt]=edge(u,w,head[v]);
                head[v]=cnt++;
            }
            dfs(0,-1);
            for(int i=0;i<n;i++)
                myinsert(dp[i]);
            for(int i=0;i<n;i++)
            {
                maxx=max(maxx,query(dp[i]));
            }
            printf("%d
    ",maxx);
        }
        return 0;
    }
    
  • 相关阅读:
    2049
    2046 ACM 数学
    1290 ACM 数学
    2017 ACM 字符串的本质
    1171 Big Event in HDU 01背包
    2045 数学:排列组合
    git命令(版本控制之道读书笔记)
    mysql:赋予用户权限、查看及修改端口号
    Linux系统的命令别名功能(转)
    回到上次目录、历史命令查找快捷方式及执行时间显示设置、查看系统版本
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754824.html
Copyright © 2011-2022 走看看