给你n 个点 m条边 图是联通的 给出一个定义为 一条路径上的 xor路径为 这条路上的 所有边的异或和
给你一个q 查询 每次给出 x,y 问 x点到y点最短的的 xor路径是多少
首先一想 查询最小异或 那就是线性基的题目 但是如何转换为线性基呢
线性基是利用基底 去 获得所有 张成
若此图是一个连通图且无环的话
那么最小xor路径 只能是 x点到y点的路
若此图是一个连通图且有环的话
若x点到y点途径过的点是有环的话 那么可以利用这个环 去获得另一个异或值
所以这个环上的值可以成为基底
所以我们可以先记录一组生成树 然后利用生成树去找环
将环路径 加入到线性基里面去
#include<iostream>
#include<vector>
using namespace std;
const int N = 1e4 + 10;
typedef long long ll;
struct node{
int x;ll w;
};
struct node2{
int x,to;ll w;
};
vector<node>v1[N];
vector<node2>v2;
int fa[N];
int get(int x){
if(fa[x] == x) return x;
return fa[x] = get(fa[x]);
}
void add(int a,int b,ll c){
v1[a].push_back({b,c});
v1[b].push_back({a,c});
}
ll pre[N];
void dfs(int x,int lastt,ll w){
pre[x] = w;
for(auto i : v1[x]){
if(i.x == lastt) continue;
ll s = w ^ i.w;
dfs(i.x,x,s);
}
}
ll d[100];
void insert(ll x){
for(int i = 62; i >= 0; i--){
if(x & (1ll << i)){
if(d[i]) x ^= d[i];
else{
d[i] = x;
break;
}
}
}
return;
}
ll get_minn(ll x){
for(int i = 62; i >= 0; i--){
if(x & (1ll << i)){
x ^= d[i];
}
}
return x;
}
int main(){
int n,m,k;
cin >> n >> m >> k;
for(int i = 1; i <= n; i++){
fa[i] = i;
}
for(int i = 1; i <= m; i++){
int x,y;ll z;
scanf("%d%d%lld",&x,&y,&z);
int dx = get(x),dy = get(y);
if(dx != dy){
fa[dx] = dy;
add(x,y,z);
}else{
v2.push_back({x,y,z});
}
}
dfs(1,0,0);
for(auto i : v2){
insert(pre[i.x] ^ pre[i.to] ^ i.w);
}
for(int i = 1; i <= k; i++){
int x,y;
scanf("%d%d",&x,&y);
printf("%lld\n",get_minn(pre[x] ^ pre[y]));
}
return 0;
}