图片说明
题意:求任意两点的异或最短路

思路:
假设点x到点y必须经过一条边,那么它可以通过走环来减少路径的异或和(如果和环的异或值 异或后更小)
如图,
特别的

图片说明

我们可以先以1为根,建一颗树,跑出1到所有点的异或值,此时往树中加边一定会形成一个环,所以在建树时没有跑过的边对应一个环,这个环的异或值为
按二进制存环的异或值,一般情况,环的异或值二进制最高位为第位则存在中;特别的,当存了一个或多个环时,,如果下一位为空则存入反之继续。假如两个环的异或值最高为都是第位,分别为,假设处理后,那么表示的是这两个环都走一遍,而可以通过得到。

接下来计算任意两个点的异或最短路,假设,我们要求的就是走那些环可以减少dis的值,从而得到异或最短路。前面已经按二进制位预处理了所有环的异或值,只要按二进制位最高位从高到低考虑,不断取最小值,考虑到的是先消去dis的高位一定是最优的,所以不能从低到高来。

MyCode:

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e4+7,maxm=2e5+7,N=1e5+7;
typedef long long int ll;
typedef unsigned long long ull;
int head[maxn],x[N],y[N],to[maxm],id[maxm],Next[maxm],tot;
ll val[maxm],edg[N];
inline void add(int a,int b,ll v) {
    to[++tot]=b;
    Next[tot]=head[a];
    val[tot]=v;
    head[a]=tot;
}
ll d[maxn],a[60],pw[60];
bool vis[maxn],f[N];
void dfs(int x) {
    vis[x]=true;
    for(int i=head[x],k=to[i];i;i=Next[i],k=to[i]) {
        if(!vis[k]) {
            d[k]=d[x]^val[i];
            f[id[i]]=1;
            dfs(k);
        }
    }
}
void ins(ll x) {
    for(int i=59;~i;--i) {
        if(pw[i]&x)  {
            if(a[i]) x^=a[i];
            else {
                a[i]=x;
                break;
            }
        }
    }
}
ll solve(ll x) {
    for(int i=59;~i;--i) if(a[i])
        x=min(x,x^a[i]);
    return x;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    pw[0]=1;
    for(int i=1;i<=59;++i) pw[i]=pw[i-1]<<1;
    int n,m,Q;
    cin>>n>>m>>Q;
    for(int i=1;i<=m;++i) {
        cin>>x[i]>>y[i]>>edg[i];
        add(x[i],y[i],edg[i]);id[tot]=i;
        add(y[i],x[i],edg[i]);id[tot]=i;
    }
    dfs(1);
    for(int i=1;i<=m;++i) if(!f[i]) ins(d[x[i]]^d[y[i]]^edg[i]);
    int xx,yy;
    while(Q--) {
        cin>>xx>>yy;
        cout<<solve(d[xx]^d[yy])<<'\n';
    }
    return 0;;
}