题目大意:
一棵树上每条边有个值,求在树中找一条路径使得路径上的边的权值的抑或和最大。
分析:
A^A^B = B;对于每个点,我们先求出它到根节点的抑或和,然后插入到01字典树中去,并且把这些值存到容器中,因为每个值都对应图中的一个节点。
最后在枚举就好了。
const int maxn = 1e5 + 10;
int head[maxn], nxt[maxn<<1], pnt[maxn<<1], val[maxn<<1], ecnt;
int n;
struct Tire {
int root;
int g[maxn*32][2];
int sz;
void init() {
root = 0;
sz = 0;
memset(g[0], -1,sizeof g[0]);
}
void insert(int value) {
int p = root;
for (int i = 30;i >= 0;--i) {
int id = (value>>i) & 1;
if (g[p][id] == -1) {
sz++;
g[p][id] = sz;
g[sz][0] = g[sz][1] = -1;
}
p = g[p][id];
}
}
int find(int value) {
int p = root;
int ans = 0;
for (int i = 30;i >= 0;--i) {
int v = ((value>>i)&1)^1;
if (g[p][v] != -1) {
ans |= (1<<i);
p = g[p][v];
}else {
p = g[p][v^1];
}
}
return ans;
}
}solve;
vector<int> vec;
void dfs(int u,int fa,int value) {
vec.push_back(value);
solve.insert(value);
for (int i = head[u];i != -1;i = nxt[i]) {
int v = pnt[i];
if (v == fa) continue;
dfs(v, u, value ^ val[i]);
}
}
int main(int argc, const char * argv[])
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
// clock_t _ = clock();
while(scanf("%d",&n) != EOF) {
memset(head, -1,sizeof head),ecnt = 0;
int u, v, w;
for (int i = 1;i < n;++i) {
scanf("%d%d%d", &u,&v,&w);
u++;
v++;
pnt[ecnt] = v, val[ecnt] = w, nxt[ecnt] = head[u], head[u] = ecnt++;
pnt[ecnt] = u, val[ecnt] = w, nxt[ecnt] = head[v], head[v] = ecnt++;
}
vec.clear();
solve.init();
dfs(1, 0, 0);
int size = vec.size();
int ans = 0;
for (int i = 0;i < size;++i) {
ans = max(ans, solve.find(vec[i]));
}
cout << ans << endl;
}
// printf("\nTime cost: %.2fs\n", 1.0 * (clock() - _) / CLOCKS_PER_SEC);
return 0;
}