【题目链接】
【思路要点】
- 任取一条1到\(N\)的路径,考虑一个与其相交的环,显然,我们可以半路“绕”一次这个环,使路径的权值Xor上环的权值。这启发我们问题很可能与线性基有关。
- 再考虑一个不与其相交的环,由于图的联通性,我们可以走出路径“绕”一次这个环,再原路返回,多走的路被走了两次,Xor和为0。因此,路径的权值同样Xor上了环的权值。
- 所以,我们如果能知道图中所有环的权值,并制成线性基,接下来只需要任取一条1到\(N\)的路径,将其权值放入线性基中贪心即可。
- 图中环的个数可能是指数级的,但它们都可以通过一些基本环Xor得到。
- 任取一棵生成树,所有非树边与树上的一段路径对应了一个环,可以证明,由这些环相互Xor,可以得到图中所有的环。
- 所以,对这些环权值求线性基,将路径权值放入线性基中贪心即可。
- 时间复杂度\(O((N+M)LogV)\)。
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 100005 #define MAXLOG 62 struct edge {int dest; long long len; }; vector <edge> a[MAXN]; int n, m, f[MAXN]; int x[MAXN], y[MAXN]; long long w[MAXN], length[MAXN]; int depth[MAXN], father[MAXN][MAXLOG]; long long value[MAXN][MAXLOG], ans; bool mark[MAXN]; template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } int F(int x) { if (f[x] == x) return x; else return f[x] = F(f[x]); } void dfs(int pos, int fa, long long val) { depth[pos] = depth[fa] + 1; father[pos][0] = fa; value[pos][0] = val; for (int i = 1; i < MAXLOG; i++) { father[pos][i] = father[father[pos][i - 1]][i - 1]; value[pos][i] = value[pos][i - 1] ^ value[father[pos][i - 1]][i - 1]; } if (pos == n) ans = value[pos][MAXLOG - 1]; for (unsigned i = 0; i < a[pos].size(); i++) if (a[pos][i].dest != fa) dfs(a[pos][i].dest, pos, a[pos][i].len); } long long get(int x, int y) { long long ans = 0; if (depth[x] < depth[y]) swap(x, y); for (int i = MAXLOG - 1; i >= 0; i--) if (depth[father[x][i]] <= depth[y]) { ans ^= value[x][i]; x = father[x][i]; } if (x == y) return ans; for (int i = MAXLOG - 1; i >= 0; i--) if (father[x][i] != father[y][i]) { ans ^= value[x][i]; x = father[x][i]; ans ^= value[y][i]; y = father[y][i]; } return ans ^ value[x][0] ^ value[y][0]; } int main() { read(n), read(m); for (int i = 1; i <= n; i++) f[i] = i; for (int i = 1; i <= m; i++) { read(x[i]), read(y[i]), read(w[i]); if (F(x[i]) == F(y[i])) continue; f[F(x[i])] = F(y[i]); a[x[i]].push_back((edge) {y[i], w[i]}); a[y[i]].push_back((edge) {x[i], w[i]}); } dfs(1, 0, 0); for (int i = 1; i <= m; i++) length[i] = get(x[i], y[i]) ^ w[i]; for (int i = MAXLOG; i >= 0; i--) { long long tmp = 1ll << i; int pos = 0; for (int j = 1; j <= m; j++) if (length[j] & tmp) { pos = j; break; } if (pos == 0) continue; long long value = length[pos]; if ((ans & tmp) == 0) ans ^= value; for (int j = 1; j <= m; j++) if (length[j] & tmp) length[j] ^= value; } printf("%lld\n", ans); return 0; }