題目鏈接:傳送門
在樹中找兩個節點使他們的異或路徑最大
01trie是個好東西
比如今年十二省聯考的day1 t1,加個可持久化而已
跟普通trie相比就是每個節點存的是二進制0或1
從根到一個節點的二進制連起來存的就是一個數字
這樣可以讓你在樹上貪心
因爲深度越大的節點若爲1則這個值一定更大
比如8(1000)> 7(111)
對於這個題
處理出根節點到每個節點的異或
挨個插入到01trie中
遍歷每個節點求最大值
看代碼還是很好理解的
/**
* @Date: 2019-04-11T19:24:10+08:00
* @Last modified time: 2019-04-13T10:33:57+08:00
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <complex>
#include <algorithm>
#include <climits>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define A 2000010
#define B 2010
using namespace std;
typedef long long ll;
struct node {
int next, to, w;
}e[A];
int head[A], num;
void add(int fr, int to, int w) {
e[++num].next = head[fr];
e[num].to = to;
e[num].w = w;
head[fr] = num;
}
int ch[A][2], n, a, b, c, cnt = 1;
ll s[A];
void dfs(int fr, int faa) {
for (int i = head[fr]; i; i = e[i].next) {
int ca = e[i].to;
if (ca == faa) continue;
s[ca] = s[fr] ^ e[i].w;
dfs(ca, fr);
}
}
void insert(ll x, int fr = 1) {
for (int i = 32; i >= 0; i--) {
int pos = (x >> i) & 1; //x的從右數第i位是0還是1
if (!ch[fr][pos]) ch[fr][pos] = ++cnt;
fr = ch[fr][pos];
}
}
ll ask(ll x, int fr = 1, ll ans = 0) {
for (int i = 32; i >= 0; i--) {
int pos = (x >> i) & 1; //選擇對應位不同的繼續走
if (ch[fr][pos ^ 1]) ans += 1LL << i, fr = ch[fr][pos ^ 1];
else fr = ch[fr][pos];
}
return ans;
}
int main(int argc, char const *argv[]) {
cin >> n;
for (int i = 1; i < n; i++) cin >> a >> b >> c, add(a, b, c), add(b, a, c);
dfs(1, 0); ll ans = 0;
for (int i = 1; i <= n; i++) insert(s[i]);
for (int i = 1; i <= n; i++) ans = max(ans, ask(s[i]));
cout << ans << endl;
}