P4151 [WC2011]最大XOR和路径

首先我们随便走走会发现如果我们走了重复路,就会消掉那一段,而走重复路的先决条件是走一个环

所以我们可以考虑线性基

就是找出所有环把他们的异或值当做元素

然后我们随便找到一条合法的路径,拿他去跑线性基,跑出最大值

然后得到的就是答案qaq

正确性是我们这样每条边在环内的都一定被计入了

而所有的环都能被用这样的环异或出来

同时我们一定存在一条路径可以做到把各个元素异或上

code:


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 1e5 + 7;
const int MAXM = 2e5 + 7;
int ccnt, home[MAXN], nxt[MAXM], to[MAXM], vis[MAXN];
int n, m;
ll a[MAXN], c[MAXN], ans, w[MAXM];
inline void ct(int x, int y, ll z) {
	ccnt++;
	nxt[ccnt] = home[x];
	home[x] = ccnt;
	to[ccnt] = y;
	w[ccnt] = z;
}

inline void ins(ll x) {
	// printf("!!%lld?\n", x);
	for(ll i = 63; i >= 0; --i) {
		// if(x == 1115964016452419888)
		// printf("%lld\n", i);
		if(x >> i & 1) {
			// if(x == 1115964016452419888)
			// 	printf("%lld?%lld %lld?%lld\n", x, i, c[i], x ^ c[i]);
			if(c[i]) {
				x = x ^ c[i];
			} else {
				c[i] = x;
				break;
			}
			// puts("qwq");
		}
		// puts("??");
	}
	// puts("qwq");
	return ;
}

inline void dfs(int u, int F) {
	vis[u] = 1;
	// printf("%d %d\n", u, F);
	for(int i = home[u]; i; i = nxt[i]) {
		int v = to[i];
		if(v == F)continue;
		if(!vis[v]) {
			a[v] = a[u] ^ w[i];
			dfs(v, u);
		} else
			ins(w[i]^a[u]^a[v]);
	}
	// puts("exit");
	return ;
}

int main() {
	scanf("%d%d", &n, &m);
	ll z = 0;
	for(int i = 1, x, y; i <= m; ++i) {
		scanf("%d%d%lld", &x, &y, &z);
		ct(x, y, z);
		ct(y, x, z);
	}
	dfs(1, 0);
	// puts("qwq");
	ans = a[n];
	// printf("%lld?\n", ans);
	for(ll i = 63; i >= 0; --i) {
		if((ans ^ c[i]) > ans) {
			// printf("%lld %lld\n", i, c[i]);
			ans = ans ^ c[i];
		}
	}
	printf("%llu\n", ans);
	return 0;
}