[BZOJ 2115] [WC 2011] Xor
阿新 • • 發佈:2018-11-24
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; }