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 }