题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2115
题目大意:中文题就不解释题意了-,-
题目思路:由异或的性质我们可以知道,当我们从结点1出发走到一个环,再从这个环回到结点1,所得到的值正好是环上所有边的权值异或和。因为你走到一个环再回来,环上的边只会被走过一次,这些值就能得到,而走到环的边则会走两次,这些值就会被抵消掉。这样问题就可以转化成了,从结点1开始直接走到结点n的边权的异或和d[n],同时再走几个环所能得到最大异或值。我们可以通过dfs先找出图中的环,将环上边的异或值存在一个数组a中,这样就变成了从数组a中任取几个数使得这几个数与d[n]异或后得到的值最大,这就能用线性基来解决了。
具体实现看代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define lowbit(x) x&-x
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define IOS ios::sync_with_stdio(false)
#define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
const int inf = 0x3f3f3f3f;
const int MX = 5e4 + 5;
struct LB {
ll d[61], p[61];
int cnt, mx;
LB() {
memset(d, 0, sizeof(d));
memset(p, 0, sizeof(p));
cnt = 0, mx = 61;
}
void init() {
memset(d, 0, sizeof(d));
memset(p, 0, sizeof(p));
}
bool add(ll val) {
/*插入时判断之前是否有数会与val异或得0,判第k小时如果有为0的情况,k要减一*/
for (int i = mx - 1; i >= 0; i--) {
if (val & (1LL << i)) {
if (!d[i]) {
d[i] = val; break;
}
val ^= d[i];
}
}
return val > 0;
}
bool query(ll val) { // 查询val这个数是否存在
for (int i = mx - 1; i >= 0; i--) {
if (val & (1LL << i)) {
if (!d[i]) return 0;
val ^= d[i];
}
}
return 1;
}
ll query_max(ll val) {
ll ret = val;
for (int i = mx - 1; i >= 0; i--) if ((ret ^ d[i]) > ret) ret ^= d[i];
return ret;
}
ll query_min() {
for (int i = 0; i < mx; i++) if (d[i]) return d[i];
return 0;
}
void rebuild() {//消元,保存到p数组
cnt = 0;
for (int i = 0; i < mx; i++) {
for (int j = 0; j < i; j ++ )
if (d[i] & (1LL << j)) d[i] ^= d[j];
}
for (int i = 0; i < mx; i++) if (d[i]) p[cnt++] = d[i];
}
ll query_kth(ll k) { //使用前需要rebuild
ll ret = 0;
if (k >= (1LL << cnt)) return -1;
for (int i = cnt - 1; i >= 0; i--) if (k & (1LL << i)) ret ^= p[i];
return ret;
}
ll find(ll x) { //找x是第几大的数,需保证x一定在
ll ret = 0, c = 0;
for (int i = 0; i < mx; i++) {
if (d[i]) {
if (x >> i & 1) ret += (1LL << c);
c++;
}
}
return ret;
}
LB operator+(const LB & _A)const { //合并
LB ret = *this;
for (int i = mx - 1; i >= 0; i--) if (_A.d[i]) ret.add(_A.d[i]);
return ret;
}
} base;
int n, m, cnt;
bool vis[MX];
ll d[MX], a[MX * 20];
vector<pll>E[MX];
void dfs(int u, int fa) {
vis[u] = 1;
for (int i = 0; i < (int)E[u].size(); i++) {
pll nw = E[u][i];
int v = nw.fi; ll w = nw.se;
if (v == fa) continue;
if (!vis[v]) {
d[v] = d[u] ^ w;
dfs(v, u);
} else a[cnt++] = d[u] ^ d[v] ^ w;
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
int u, v; ll w;
scanf("%d%d%lld", &u, &v, &w);
E[u].pb(MP(v, w));
E[v].pb(MP(u, w));
}
dfs(1, 0);
for (int i = 0; i < cnt; i++) base.add(a[i]);
ll ans = base.query_max(d[n]);
cout << ans << endl;
return 0;
}