01字典树——洛谷 P4551 最长异或路径

洛谷 P4551 最长异或路径

这个题目要求的是进行求取最大的异或值,这里其实用01异或字典树维护是因为大量数字都是有一个相同的前缀,然后可以为了异或出最大值,使用贪心的方法对这个01字典树进行搜索,因为高位如果是1,就绝对比后面n个全是1都要大。因为有大量数据,所以用01字典树,可以快速处理数据,每次可以规避一半。

这里num是用来存点的值的,因为是一个树,我们直接默认1结点是根节点值为0,随后我们用链式前向星存图,然后用dfs将边值换成点值,然后将求出来的点值存到num数组中,然后将这些点的值存到trie树中这样就可以进行维护。随后找出每一个点的最大异或路径值,然后选出其中的最大值即可。

AC code:

  1 #include<iostream>
  2 #include<string>
  3 #include<cstdio>
  4 #include<cstring>
  5 using namespace std;
  6 typedef long long ll;
  7 const int maxn = 100050;
  8 int num[maxn];//用来存每个点的权值 
  9 
 10 //------------------链式前向星 
 11 struct g{
 12     int v, w,next;
 13 }edge[maxn<<1];
 14 int head[maxn];
 15 int cnt1 = 0;
 16 void add(int u, int v, int w)
 17 {
 18     edge[cnt1].next = head[u];
 19     edge[cnt1].w = w;
 20     edge[cnt1].v = v;
 21     head[u] = cnt1++;
 22 }
 23 void ini1(int n)
 24 {
 25     for(int i = 1; i <= n; i++)
 26         head[i] = -1;
 27     cnt1 = 0;
 28 }
 29 //-----------------------01字典树 
 30 int cnt;
 31 int next[maxn*32][2];
 32 int exist[maxn*32];
 33 
 34 void ini()//初始化数组 
 35 {
 36     cnt = 1;
 37     memset(next, 0, sizeof(next));
 38     memset(exist, 0, sizeof(exist));
 39 }
 40 
 41 void insert(int x)//插入数字 
 42 {
 43     int p = 0;
 44     for(int i = 31; i >= 0; i--)
 45     {
 46         int v = (x>>i)&1;
 47         if(!next[p][v])
 48             next[p][v] = cnt++;
 49         p = next[p][v];
 50     }
 51     exist[p] = x;
 52 }
 53 
 54 int find(int x)//查找最大的数字 
 55 {
 56     int p = 0;
 57     for(int i = 31; i >= 0; i--)
 58     {
 59         int v = (x>>i)&1;
 60         if(next[p][v^1])
 61             p = next[p][v^1];
 62         else p = next[p][v];
 63             
 64     }
 65     return exist[p];
 66 }
 67 
 68 
 69 //-----------------
 70 void dfs(int u, int fa)//dfs将边权化成点权 
 71 {
 72     for(int i = head[u]; ~i; i = edge[i].next)
 73     {
 74         int v = edge[i].v;
 75         if(v == fa)    continue;
 76         num[v] = num[u]^edge[i].w;
 77         dfs(v, u);
 78     }
 79     return;
 80 }
 81 
 82 int main()
 83 {
 84     ini();
 85     int n ;    
 86     scanf("%d", &n);
 87     ini1(n);
 88 
 89     int u, v, w;
 90     for(int i = 0; i < n-1; i++)
 91     {
 92         scanf("%d %d %d", &u, &v, &w);
 93         add(u, v, w);
 94         add(v, u, w);
 95     }
 96     num[1] = 0;
 97     dfs(1, 0);
 98     for(int i = 1; i <= n; i++)
 99     {
100         insert(num[i]);    
101     }
102     int max1 = -1;
103     for(int i = 1; i <= n; i++)
104     {
105         max1 = max(max1, find(num[i])^num[i]);
106     }
107     cout << max1;
108     return 0;
109 }

 

posted @ 2020-08-13 14:45  斌斌翻水水  阅读(94)  评论(0)    收藏  举报