「 Luogu P2420 」 让我们异或吧
# 解题思路
两点之间的路径的话一定经过它们两个 LCA,这一点已经是显而易见的,那么再来看看异或的性质。
$$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)$$
再回到这个题上来,因为 $a\ xor\ b\ xor\ b = a$,所以从根节点出来的一条路径我们可以预先处理一个异或和出来。
在询问的时候再将多余的路径给异或掉。设两点的 LCA 为 z,那么答案就是 $dis[tmp]\ xor\ dis[x]\ xor\ dis[tmp]\ xor\ dis[y]$
有第一条性质 $a\ xor\ b\ xor\ b = a$ 可以化简上式,答案就变成了 $dis[x]\ xor\ dis[y]$,化简后我们发现根本就不需要求 LCA。
下面给出代码。
# 代码
#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]); } }
作者:Mystical-W
来源:http://www.cnblogs.com/bljfy
说明:客官~~您如果觉得写得好的话,记得给我点赞哦。如果要转载的请在合适的地方注明出处。谢
谢您的合作。您要是有什么有疑问的地方可以在下面给我评论。也可以直接私信我哦
声明:本作品由Mystical-W采用知识共享署名-非商业性使用-禁止演绎 4.0 国
际许可协议进行许可
来源:http://www.cnblogs.com/bljfy
说明:客官~~您如果觉得写得好的话,记得给我点赞哦。如果要转载的请在合适的地方注明出处。谢
谢您的合作。您要是有什么有疑问的地方可以在下面给我评论。也可以直接私信我哦
声明:本作品由Mystical-W采用知识共享署名-非商业性使用-禁止演绎 4.0 国
际许可协议进行许可