1. 程式人生 > >樹講解(6)——讓我們異或吧

樹講解(6)——讓我們異或吧

!= 情侶 rst back cst getch 能夠 代碼 st表

洛谷——P2420 讓我們異或吧

題目描述

異或是一種神奇的運算,大部分人把它總結成不進位加法.

在生活中…xor運算也很常見。比如,對於一個問題的回答,是為1,否為0.那麽:

(A是否是男生 )xor( B是否是男生)=A和B是否能夠成為情侶

好了,現在我們來制造和處理一些復雜的情況。比如我們將給出一顆樹,它很高興自己有N個結點。樹的每條邊上有一個權值。我們要進行M次詢問,對於每次詢問,我們想知道某兩點之間的路徑上所有邊權的異或值。

輸入輸出格式

輸入格式:

輸入文件第一行包含一個整數N,表示這顆開心的樹擁有的結點數,以下有N-1行,描述這些邊,每行有3個數,u,v,w,表示u和v之間有一條權值為w的邊。接下來一行有一個整數M,表示詢問數。之後的M行,每行兩個數u,v,表示詢問這兩個點之間的路徑上的權值異或值。

輸出格式:

輸出M行,每行一個整數,表示異或值

輸入輸出樣例

輸入樣例#1:
5
1 4 9644
2 5 15004
3 1 14635
5 3 9684
3
2 4
5 4
1 1
輸出樣例#1:
975
14675
0

說明

對於40%的數據,有1 ≤ N,M ≤ 3000;

對於100%的數據,有1 ≤ N ,M≤ 100000。

思路:

我們知道異或的一個性質:異或一個數兩遍等於沒異或!

所以,我們在這裏可以對整棵樹跑一遍dfs,求出到根節點的所有節點的異或和,然後在下面進行m次詢問時,進行f[x]^f[y]就可以啦。

因為這裏我們將f[x]異或了兩次,就等於沒異或,那麽這樣我們就求出了從x到y的異或值

代碼:

#include<vector>
#include<stdio.h>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100001
#define maxn 123456
using namespace std;
vector<pair<int,int> >vec[N];
int n,x,y,z,f[N*2],fa[N*2],m; int read() { int x=0,f=1; char ch=getchar(); while(ch>9||ch<0) { if(ch==-) f=-1; ch=getchar(); } while(ch<=9&&ch>=0) { x=x*10+ch-0; ch=getchar(); } return x*f; } void dfs(int x) { for(int i=0;i<vec[x].size();i++) { if(fa[x]!=vec[x][i].first) { fa[vec[x][i].first]=x;// vec[x][i].first表示的是x連出的邊 f[vec[x][i].first]=f[x]^vec[x][i].second;//vec[x][i].second表示x連出的邊的權值 dfs(vec[x][i].first); } } } int main() { n=read(); for(int i=1;i<n;i++) { x=read(),y=read(),z=read(); vec[x].push_back(make_pair(y,z)); vec[y].push_back(make_pair(x,z)); } dfs(1); m=read(); while(m--) { x=read(),y=read(); printf("%d\n",f[x]^f[y]); } return 0; }

樹講解(6)——讓我們異或吧