您的位置:首页 > 其它

BZOJ1954: Pku3764 The xor-longest Path

2017-08-10 06:59 387 查看

 给定一棵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

[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\n",trie.ans); 113 return 0; 114 }

View Code [p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: