[WC2011]最大XOR和路径

题目链接

\(\Rightarrow \rm luogu\) 链接

题解

由于异或的自反性,可以首先随便找到一条从 \(1\)\(n\) 的路径,然后加入若干个环,这时候可以认为任何从 \(1\)\(n\) 的路径都可以由这种方式构成,为了找到最大异或和,需要使用线性基,将所有环的异或和加入。

但是环的数量显然过多,依然依赖异或自反性,用 \(\rm dfs\) 找到原图的一颗生成树,要加入的环就只有只存在一条非树边的环,容易想到可以用多个这样的环拼凑出所有的环。

加强版题目是 \(\text{CF938G Shortest Path Queries}\) ,因为太菜,先咕着。

参考代码

typedef long long LL;

const int maxn = 5e4 + 5, maxm = 1e5 + 5;
LL bst[65];
void ins(LL x) {
	for (int i = 60; i >= 0; i--) if ((x >> i) & 1) {
		if (!bst[i]) { bst[i] = x; break; }
		x ^= bst[i];
	}
}
LL qry(LL x) {
	LL res = x;
	for (int i = 60; i >= 0; i--) res = max(res, res ^ bst[i]);
	return res;
}

struct Edge {
	int v, nex; LL w;
	Edge(int v = 0, int nex = 0, LL w = 0) : v(v), nex(nex), w(w) {} 
} E[maxm << 1];
int hd[maxn], tote;
void addedge(int u, int v, LL w) {
	E[++tote] = Edge(v, hd[u], w), hd[u] = tote;
	E[++tote] = Edge(u, hd[v], w), hd[v] = tote;
}

LL xs[maxn]; int vis[maxn];
void dfs(int u, int fa, LL xs_u) {
	xs[u] = xs_u, vis[u] = 1;
	for (int i = hd[u]; i; i = E[i].nex) {
		int v = E[i].v;
		if (vis[v]) {
			if (v != fa) ins(xs_u ^ E[i].w ^ xs[v]);
			continue;
		}
		dfs(v, u, xs_u ^ E[i].w);
	}
}

int main() {
	int n, m; scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; i++) {
		int u, v; LL w; scanf("%d%d%lld", &u, &v, &w);
		addedge(u, v, w);
	}
	dfs(1, 0, 0);
	printf("%lld\n", qry(xs[n]));
	return 0;
}
posted @ 2022-03-13 20:06  juruohjr  阅读(32)  评论(0编辑  收藏  举报