樹講解(6)——讓我們異或吧
阿新 • • 發佈:2017-05-07
!= 情侶 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)——讓我們異或吧