• BZOJ1954: Pku3764 The xor-longest Path


     给定一棵n<=100000个点的带权树,求树上最长的异或和路径。

    “求树上最xx路径”“统计树上xx路的方案数”,本来想用点分的,然后想处理出根节点到每个点的亦或路径时如何统计答案避免判重,突然发现:根节点到A的路径亦或根节点到B的路径就是A到B的路径!

    于是预处理(用bfs,避免爆栈)出根节点到每个节点的亦或路径之后,问题变成在这个长度n的数组中选两个数使亦或和最大。

    先把每个数按二进制位从高到低丢进Trie,然后

    方法一:枚举每个数,在Trie上每一位尽量往反方向跳,比如数1010,就尽量跳成0101,除非某一位没有反方向不得不跳同方向,边跳边更新答案。

    方法二:开两个指针,从Trie根节点直接往下走,能走反方向就走反方向,比如p往0走q就往1走,如果出现多种“反方向”的选择,就每种选择都跑一遍取Max。

    下面是方法二代码。

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #include<string.h>
      4 #include<algorithm>
      5 //#include<iostream>
      6 using namespace std;
      7 
      8 int n;
      9 #define maxn 100011
     10 #define LL long long
     11 int x,y,v;
     12 struct Edge{int to,v,next;};
     13 int num[maxn],lnum=0;
     14 int que[maxn],head,tail;
     15 struct Tree
     16 {
     17     int first[maxn];Edge edge[maxn*2];int le;
     18     Tree() {memset(first,0,sizeof(first));le=2;}
     19     void in(int x,int y,int v)
     20     {
     21         Edge &e=edge[le];
     22         e.to=y;e.v=v;
     23         e.next=first[x];
     24         first[x]=le++;
     25     }
     26     void insert(int x,int y,int v)
     27     {
     28         in(x,y,v);
     29         in(y,x,v);
     30     }
     31     void bfs(int x)
     32     {
     33         que[head=(tail=1)-1]=x;
     34         memset(num,-1,sizeof(num));
     35         num[x]=0;
     36         while (head!=tail)
     37         {
     38             const int now=que[head++],d=num[now];
     39             for (int i=first[now];i;i=edge[i].next)
     40                 if (num[edge[i].to]==-1)
     41                 {
     42                     num[edge[i].to]=d^edge[i].v;
     43                     que[tail++]=edge[i].to;
     44                 }
     45         }
     46     }
     47 }t;
     48 struct Trie
     49 {
     50     int ch[maxn*25][2],cnt[maxn*25];
     51     int size;
     52     Trie()
     53     {
     54         size=0;
     55         ch[0][0]=ch[0][1]=0;
     56         cnt[0]=0;
     57     }
     58     void insert(int v)
     59     {
     60         int now=0;
     61         bool bin[33];
     62         for (int i=1;i<=31;i++)
     63         {
     64             bin[i]=v&1;
     65             v>>=1;
     66         }
     67         for (int i=31;i>=1;i--)
     68         {
     69             if (!ch[now][bin[i]])
     70             {
     71                 size++;
     72                 ch[size][0]=ch[size][1]=0;
     73                 ch[now][bin[i]]=size;
     74                 cnt[size]=0;
     75             }
     76             now=ch[now][bin[i]];
     77         }
     78         cnt[now]++;
     79     }
     80     int ans;
     81     int play(int p,int q,int dep)
     82     {
     83         if (!dep) return 0;
     84         int base=1<<(dep-1);
     85         if (!ch[p][1])
     86         {
     87             if (!ch[q][1]) return play(ch[p][0],ch[q][0],dep-1);
     88             else return base^play(ch[p][0],ch[q][1],dep-1);
     89         }
     90         if (!ch[p][0])
     91         {
     92             if (!ch[q][0]) return play(ch[p][1],ch[q][1],dep-1);
     93             else return base^play(ch[p][1],ch[q][0],dep-1);
     94         }
     95         if (!ch[q][0]) return base^play(ch[p][0],ch[q][1],dep-1);
     96         if (!ch[q][1]) return base^play(ch[p][1],ch[q][0],dep-1);
     97         if (p==q) return base^play(ch[p][0],ch[q][1],dep-1);
     98         return max(base^play(ch[p][0],ch[q][1],dep-1),base^play(ch[p][1],ch[q][0],dep-1));
     99     }
    100 }trie;
    101 int main()
    102 {
    103     scanf("%d",&n);
    104     for (int i=1;i<n;i++)
    105     {
    106         scanf("%d%d%d",&x,&y,&v);
    107         t.insert(x,y,v);
    108     }
    109     t.bfs(n/2);
    110     for (int i=1;i<=n;i++) trie.insert(num[i]);
    111     trie.ans=trie.play(0,0,31);
    112     printf("%d
    ",trie.ans);
    113     return 0;
    114 }
    View Code
  • 相关阅读:
    linux创建用户和组
    ftp上来显示的时间和系统时间不一致
    在Linux下如何用Shell脚本读写XML?现有一个config.xml(转)
    关于业务主键和逻辑主键
    git push 提示
    浏览器默认样式
    css实现缩进无限嵌套
    使用设置报头x-Frame-Options限制iframe网页嵌套
    chrome控制台小技巧
    git版本库底层命令
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7337186.html
Copyright © 2020-2023  润新知