1. 程式人生 > >[洛谷P4551]最長異或路徑

[洛谷P4551]最長異或路徑

題目大意:求樹上最長的異或路徑

題解:由於異或具有自反性,只需要求出每個節點到根的異或長度,塞進$Trie$裡,最後對每個節點找一下最大值更新答案即可

卡點:把動態開點寫成了可持久化,然後導致根不可以包括所有節點(其實我也不知道為什麼)

 

C++ Code:

#include <algorithm>
#include <cstdio>
#define M 30
#define maxn 100010
#define N (maxn * (M + 1))

int head[maxn], cnt;
struct Edge {
	int to, nxt, w;
} e[maxn << 1];
inline void addedge(int a, int b, int c) {
	e[++cnt] = (Edge) {b, head[a], c}; head[a] = cnt;
	e[++cnt] = (Edge) {a, head[b], c}; head[b] = cnt;
}

int nxt[N][2], root, idx;
void insert(int &rt, int x, int dep) {
	if (!rt) rt = idx++;
	if (!~dep) return ;
	insert(nxt[rt][x >> dep & 1], x, dep - 1);
}
int query(int x) {
	int res = 0, rt = root;
	for (int i = M; ~i; i--) {
		int tmp = x >> i & 1;
		if (nxt[rt][!tmp]) rt = nxt[rt][!tmp], res |= 1 << i;
		else rt = nxt[rt][tmp];
	}
	return res;
}

int n, dis[maxn];
void dfs(int u, int fa = 0) {
	insert(root, dis[u], M);
	for (int i = head[u]; i; i = e[i].nxt) {
		int v = e[i].to;
		if (v != fa) {
			dis[v] = dis[u] ^ e[i].w;
			dfs(v, u);
		}
	}
}
int main() {
	scanf("%d", &n);
	for (int i = 1, a, b, c; i < n; i++) {
		scanf("%d%d%d", &a, &b, &c);
		addedge(a, b, c);
	}
	dfs(1);
	int ans = 0;
	for (int i = 1; i <= n; i++) ans = std::max(ans, query(dis[i]));
	printf("%d\n", ans);
	return 0;
}