【D.都市的柏油路太硬】克鲁斯卡尔重构树的板子题,直接套板子就行了。

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 2e5 + 5;  // 点
const int M = 5e5 + 5;  // 边
int n, m;               // 点,边

// ==========================================================================
// 题目定义的随机数
typedef unsigned long long ull;
ull myRand(ull &k1, ull &k2) {
    ull k3 = k1, k4 = k2;
    k1 = k4;
    k3 ^= (k3 << 23);
    k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
    return k2 + k4;
}
pair<int, int> myRanq(ull &k1, ull &k2, int MAXN) {
    int x = myRand(k1, k2) % MAXN + 1, y = myRand(k1, k2) % MAXN + 1;
    if (x > y)
        return make_pair(y, x);
    else
        return make_pair(x, y);
}
// ==========================================================================
namespace LCA {
int dep[N], dfn[N], n;
int st[N << 1][35], lg2[35];

struct Edge {
    int to, next;
} edge[N << 1];

int head[N], edge_cnt;

void init() {
    edge_cnt = 0;
    memset(head, -1, sizeof head);
}

void Insert(int u, int v) {  // 插入邻接表
    edge[++edge_cnt].to = v;
    edge[edge_cnt].next = head[u];
    head[u] = edge_cnt;
}

void dfs(int u, int fa) {
    dfn[u] = ++n;  // dfs序(欧拉序列,n'=2n-1)
    dep[u] = dep[fa] + 1;
    st[n][0] = u;
    for (int i = head[u]; ~i; i = edge[i].next) {
        int v = edge[i].to;
        if (v == fa) continue;
        dfs(v, u);
        st[++n][0] = u;
    }
}

void build(int root) {
    n = 0;
    dfs(root, 0);

    lg2[1] = 0;  // log_2
    for (int i = 2; i <= n; i++) lg2[i] = lg2[i >> 1] + 1;
    for (int j = 1; (1 << j) <= n; j++) {  // 初始化st表(Range min_dfn query)
        for (int i = 1; i + (1 << j) <= n + 1; i++) {
            if (dep[st[i][j - 1]] < dep[st[i + (1 << (j - 1))][j - 1]])
                st[i][j] = st[i][j - 1];
            else
                st[i][j] = st[i + (1 << (j - 1))][j - 1];
        }
    }
}

int query(int u, int v) {
    int lef = dfn[u], rig = dfn[v], t = lg2[abs(rig - lef) + 1];
    if (lef > rig) swap(lef, rig);
    if (dep[st[lef][t]] < dep[st[rig - (1 << t) + 1][t]])
        return st[lef][t];
    else
        return st[rig - (1 << t) + 1][t];
}
};  // namespace LCA
// ==========================================================================
namespace Ex_Kruskal {
struct Edge {
    int u, v;
    ll w;
    bool operator<(const Edge &b) const { return w < b.w; }
} edge[M];

ll fa[N], val[N];
int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }

void init() {
    iota(fa, fa + N, 0);
    LCA::init();
}
void build(int m) {
    sort(edge, edge + m);
    for (int i = 0; i < m; i++) {
        int x = find(edge[i].u), y = find(edge[i].v);
        if (x != y) {
            val[++n] = edge[i].w;
            fa[x] = fa[y] = n;
            LCA::Insert(n, x);
            LCA::Insert(n, y);
        }
    }
    LCA::build(n);
}
int query(int u, int v) { return val[LCA::query(u, v)]; }

};  // namespace Ex_Kruskal

// ==========================================================================
// 快读
template <typename T>
inline void read(T &x) {
    T f = 1;
    x = 0;
    char ch = getchar();
    while (0 == isdigit(ch)) {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (0 != isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
    x *= f;
}
// ==========================================================================

int main() {
    read(n), read(m);  // 读入点数和边数
    int maxn = n;

    Ex_Kruskal::init();  // 初始化Ex_Kruskal

    for (int i = 0; i < m; i++) {  // 读入边(带权值)
        read(Ex_Kruskal::edge[i].u);
        read(Ex_Kruskal::edge[i].v);
        read(Ex_Kruskal::edge[i].w);
    }

    Ex_Kruskal::build(m);  // 构建Ex_Kruskal,参数(边数)

    int q;
    read(q);
    ull ans = 0, k1, k2;
    scanf("%llu%llu", &k1, &k2);
    while (q--) {
        pair<int, int> opt = myRanq(k1, k2, maxn);
        int u = opt.first, v = opt.second;
        ans ^= Ex_Kruskal::query(u, v);  // 查询
    }
    printf("%llu", ans);
    return 0;
}