「 Luogu P2420 」 讓咱們異或吧

# 解題思路

兩點之間的路徑的話必定通過它們兩個 LCA,這一點已是顯而易見的,那麼再來看看異或的性質。ios

$$a\ xor\ b\ xor\ b = a\\ a\ xor\ a=0\\ a\ xor\ 0 = a\\ a\ xor\ b = b\ xor\ a\\ a\ xor\ b\ xor\ c = a\ xor\ (b\ xor\ c)$$spa

再回到這個題上來,由於 $a\ xor\ b\ xor\ b = a$,因此從根節點出來的一條路徑咱們能夠預先處理一個異或和出來。code

在詢問的時候再將多餘的路徑給異或掉。設兩點的 LCA 爲 z,那麼答案就是 $dis[tmp]\ xor\ dis[x]\ xor\ dis[tmp]\ xor\ dis[y]$blog

有第一條性質 $a\ xor\ b\ xor\ b = a$ 能夠化簡上式,答案就變成了 $dis[x]\ xor\ dis[y]$,化簡後咱們發現根本就不須要求 LCA。get

下面給出代碼。string

 

# 代碼

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const int maxn = 1e5+3;
int n, m, head[maxn], cnt, dis[maxn], rt = 1, fa[maxn][32];
struct edge {int to, w, nxt;} ed[maxn << 1];
void read(int &x) {
    x = 0; int f = 1; char c = getchar();
    while (c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while (c <= '9' && c >= '0') {x = x*10 + c-'0'; c = getchar();}
    x *= f;
}
struct HAHA {
    void addedge(int u, int v, int w) {
        ed[++cnt].nxt = head[u], head[u] = cnt, ed[cnt].to = v, ed[cnt].w = w;
    }
    void dfs(int u) {
        for(int i=head[u]; i; i=ed[i].nxt) {
            if(ed[i].to == fa[u][0]) continue;
            dis[ed[i].to] = dis[u] ^ ed[i].w;
            fa[ed[i].to][0] = u;
            dfs(ed[i].to);
        }
    }
}T;
int main() {
    read(n);
    int x, y, z;
    for(int i=1; i<n; i++) {
        read(x), read(y), read(z);
        T.addedge(x, y, z), T.addedge(y, x, z);
    }
    T.dfs(rt);
    read(m);
    for(int i=1; i<=m; i++) {
        read(x), read(y);
        printf("%d\n", dis[x]^dis[y]);
    }
}
相關文章
相關標籤/搜索