BZOJ 2115: [Wc2011] Xor

图上 \(1 \to n\) 的任意一条路径的异或和都可以由图上若干个环以及一条 \(1 \to n\) 的路径的异或得到
dfs求出所有环,求出线性基,再贪心地从高到低位得到最大异或和

#include <bits/stdc++.h>
#define ll long long
#define P pair<int, ll>
#define pb push_back
using namespace std;

template<typename T>
inline void read(T &x) {
	x = 0;T f = 1; char ch = getchar();
	while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
	x *= f;
}

const int N = 5e4 + 10;
vector<P> G[N];
ll dis[N], d[N * 100], p[N];
int n, m, cnt;
bool vis[N];

void dfs(int u) {
	vis[u] = 1;
	for (int i = 0; i < G[u].size(); i++) {
		P pp = G[u][i];
		int v = pp.first; ll c = pp.second;
		if (!vis[v]) dis[v] = dis[u] ^ c, dfs(v);
		else d[++cnt] = dis[v] ^ dis[u] ^ c;
	}
}

int main() {
	read(n); read(m);
	while (m--) {
		int u, v; ll c;
		read(u); read(v); read(c);
		G[u].pb((P){v, c});
		G[v].pb((P){u, c});
	}
	dfs(1);
	ll ans = dis[n];
	for (int i = 1; i <= cnt; i++) {
		for (int j = 61; ~j; j--) {
			if (d[i] >> j & 1) {
				if (!p[j]) { p[j] = d[i]; break; }
				d[i] ^= p[j];
			}
		}
	}
	for (int j = 61; ~j; j--) {
		if ((ans ^ p[j]) > ans) ans ^= p[j];
	}
	printf("%lld\n", ans);
	return 0;
}
posted @ 2020-02-20 13:30  Mrzdtz220  阅读(83)  评论(0)    收藏  举报