题意
题解
异或运算和与运算、或运算不同,没有单调性,难以使用一般求最短路的方法求解此问题。
考虑环,显然图中环的异或值都是可以取到的。考虑两种情况,环不在路径上,那么可以反复经过某一条通向环的路径,且此路径没有贡献;环在路径上,那么将换上的原路径部分替换为环上非原路径的部分。那么 D F S DFS DFS 求图中所有简单环的异或值,构造线性基。任取一条 1 → N 1\rightarrow N 1→N 的路径,从高位向低位不断尝试异或这一位的线性基,求最大值即可。
由于求解最大值时从高位向低位依次处理,构造线性基时只用保证第 i i i 对应的线性基的高位为零即可,不一定要消去第 i i i 位其余的 1 1 1。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define maxl 60
#define maxn 50005
typedef long long ll;
struct edge
{
int to;
ll cost;
};
int N, M;
ll dis[maxn], B[maxl + 1];
bool used[maxn];
vector<edge> G[maxn];
void insert(ll n)
{
for (int i = maxl; i >= 0; --i)
{
if (n >> i & 1)
{
if (B[i])
n ^= B[i];
else
{
B[i] = n;
break;
}
}
}
}
void dfs(int p, int v, ll d)
{
used[v] = 1, dis[v] = d;
for (int i = 0; i < (int)G[v].size(); ++i)
{
edge &e = G[v][i];
if (!used[e.to])
dfs(v, e.to, d ^ e.cost);
else if (e.to != p)
insert(d ^ e.cost ^ dis[e.to]);
}
}
int main()
{
scanf("%d%d", &N, &M);
for (int i = 0; i < M; ++i)
{
int s, t;
ll d;
scanf("%d%d%lld", &s, &t, &d);
G[s].push_back(edge{t, d});
G[t].push_back(edge{s, d});
}
dfs(0, 1, 0);
ll res = dis[N];
for (int i = maxl; i >= 0; --i)
if (!(res >> i & 1))
res ^= B[i];
printf("%lld\n", res);
return 0;
}