Problem:
K - XOR回廊

問題文

KU大学では一風変わったラリーゲームが人気である．
このゲームの舞台であるサーキットには，N 個の休憩所と M 個の道があり，i 番目の道は fi 番目の休憩所と ti 番目の休憩所の間にある．
すべての道にはチェックポイントが一つずつ存在し，道 i のチェックポイントを通過するとどちらの向きで通っても pi の得点がXORで加算される．XORで加算される．大事なことなので2回言いました．

このゲームでは，同じ休憩所や道を何度通っても良いし，
ゴールにたどり着いてもそのままラリーを続行することができるが，
道の途中にあるチェックポイントを迂回して別の休憩所へ行くことは禁止されている．
そのため，どのような道順をたどれば高い得点を取ることができるかを頑張って考えなければならない点が人気のある所以である．

今回は Q 人の参加者がいて，j 番目の参加者は aj の休憩所からスタートして，ゴールである bj の休憩所まで行くことになっているようだ．
運営側の人間としてそれぞれの参加者の最高得点を前もって調べておくことにした．

入力形式

入力は以下の形式で与えられる．なお休憩所の番号は0-indexedである．

N M Q
f1 t1 p1
...
fM tM pM
a1 b1
...
aQ bQ

出力形式

Q 行出力し，j 行目には aj 番目の休憩所から bj 番目の休憩所への経路で得られる得点の最大値を出力せよ．

制約

1 ≤ N ≤ 105

0 ≤ M ≤ 2 × 105

1 ≤ Q ≤ 105

0 ≤ fi, ti < N, fi ≠ ti

0 ≤ pi < 260

0 ≤ aj, bj < N

どの休憩所からでも，道を辿っていけば任意の休憩所へたどり着ける．

休憩所 fi,ti 間を結ぶ道は高々一つしか存在しない．

入力値はすべて整数である．

この問題の判定には，60 点分のテストケースのグループが設定されている．このグループに含まれるテストケースは上記の制約に加えて下記の制約も満たす．

M ≤ 20

入出力例

入力例1

5 5 3
0 1 7
1 2 22
2 3 128
3 4 128
4 2 128
0 1
0 0
3 4

出力例1

135
128
128

Writer : 森槙悟
Tester : 田村和範

Solution in C++ (judge verdict: Accepted)

#include <stdio.h>
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define mp make_pair
typedef long long Int;

int N, M, Q;
vector<pair<int, Int> > g[200000];
Int hi[200000], cy[64];
bool vis[200000];

void add(Int b) {
    for (int x = 63; b; x--) if (b&(1LL<<x)) {
        if (cy[x] == 0) { cy[x] = b; return ; }
        b ^= cy[x];
    }
}

void rec(int at, int pre, Int bit) {
    if (vis[at]) {
        add(bit^hi[at]);
        return ;
    }
    vis[at] = 1;
    hi[at] = bit;
    rep (i, g[at].size()) {
        const int to = g[at][i].first;
        if (to == pre) continue;
        rec(to, at, bit^g[at][i].second);
    }
}

void build() {
    rec(0, -1, 0);
}

Int solve(int u, int v) {
    Int ans = hi[u]^hi[v];
    for (int x = 63; x >= 0; x--) if (!(ans&(1LL<<x))) ans ^= cy[x];
    return ans;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N >> M >> Q;
    rep (i, M) {
        int f, t;
        Int p;
        cin >> f >> t >> p;
        g[f].push_back(mp(t, p));
        g[t].push_back(mp(f, p));
    }
    build();
    rep (_, Q) {
        int a, b;
        cin >> a >> b;
        cout << solve(a, b) << endl;
    }
    return 0;
}