[WC2011]最大XOR和路径
题目链接
题解
由于异或的自反性,可以首先随便找到一条从 \(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;
}