Solution
我们可以先算出一条路径的异或和。
首先我们可以证明所有的环都是可以取的。首先从 \(1\) 走到环,再走回去,中间的路径异或和会正好被消去。
其次这样做是对的。两条从起点到终点的路径必定会形成一个环,无论两条路径是否有重合部分,异或一下这个环就能获得这个路径。
有一个没搞懂的地方:环的个数要开 \(M*2\) 才能过,以后还是开容器吧 \(QWQ\)。
Code
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 5e4 + 5;
int tot, cnt, n, m, head[N], nxt[N << 2], dot[N << 2];
ll val[N << 2], loop[N << 2], s[N], d[65];
bool vis[N];
ll read() {
ll x = 0, f = 1; char s;
while((s = getchar()) < '0' || s > '9') if(s == '-') f = -1;
while(s >= '0' && s <= '9') {x = (x << 1) + (x << 3) + (s ^ 48); s = getchar();}
return x * f;
}
void addEdge(const int u, const int v, const ll w) {
nxt[++ cnt] = head[u], dot[cnt] = v, head[u] = cnt, val[cnt] = w;
}
void dfs(const int u) {
vis[u] = 1;
for(int i = head[u]; i; i = nxt[i]) {
int v = dot[i];
if(vis[v]) loop[++ tot] = s[u] ^ s[v] ^ val[i];
else s[v] = s[u] ^ val[i], dfs(v);
}
}
void ins(ll x) {
for(int i = 62; ~i; -- i)
if(x & (1ll << i)) {
if(! d[i]) {d[i] = x; return;}
else x ^= d[i];
}
}
ll Max(ll x) {
for(int i = 62; ~i; -- i) x = max(x, x ^ d[i]);
return x;
}
int main() {
int u, v; ll w;
while(~ scanf("%d %d", &n, &m)) {
tot = cnt = 0;
memset(vis, 0, sizeof vis);
memset(head, 0, sizeof head);
memset(s, 0, sizeof s);
memset(d, 0, sizeof d);
for(int i = 1; i <= m; ++ i) {
u = read(), v = read(), w = read();
addEdge(u, v, w); addEdge(v, u, w);
}
dfs(1);
for(int i = 1; i <= tot; ++ i) ins(loop[i]);
printf("%lld\n", Max(s[n]));
}
return 0;
}