Description
选择一条 \(1\) 到 \(n\) 的路径使得所经过的边权的异或和最大。
Solution
好题。题解
注意找 \(1\) ~ \(n\) 的路径时,每个点只能访问一次。
Code
#include <cstdio>
#include <algorithm>
typedef long long LL;
const int N = 50005, M = 200005;
struct Edge {
int v; LL w;
} e[M];
int head[N], nxt[M], tot, n, m, cnt, vis[N]; LL a[M], b[N], p[65], ans;
void adde(int u, int v, LL w) {
nxt[++tot] = head[u];
head[u] = tot;
e[tot].v = v, e[tot].w = w;
}
void dfs1(int u, int f, LL d) { //找一条1~n的路径
vis[u] = 1;
if (u == n) { ans = d; return; }
for (int i = head[u]; i; i = nxt[i]) {
if (vis[e[i].v]) continue;
dfs1(e[i].v, u, d ^ e[i].w);
if (ans) return;
}
}
void dfs2(int u, int f, LL d) { //找环
b[u] = d, vis[u] = 2;
for (int i = head[u]; i; i = nxt[i]) {
if (e[i].v == f) continue;
if (vis[e[i].v] == 2) a[++cnt] = b[e[i].v] ^ d ^ e[i].w;
else dfs2(e[i].v, u, d ^ e[i].w);
}
}
void insert(LL x) {
for (int i = 62; ~i; --i) {
if (!(x >> i)) continue;
if (!p[i]) { p[i] = x; break; }
x ^= p[i];
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; ++i) {
int u, v; LL w;
scanf("%d%d%lld", &u, &v, &w);
adde(u, v, w), adde(v, u, w);
}
dfs1(1, 0, 0), dfs2(1, 0, 0);
for (int i = 1; i <= cnt; ++i) insert(a[i]);
for (int i = 62; ~i; --i)
if ((ans ^ p[i]) > ans) ans ^= p[i];
printf("%lld\n", ans);
return 0;
}