洛谷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。

代码

#include<cstdio>
#define MAXN 100005 
using namespace std;


inline int read(){
    int num=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')num=num*10+ch-48,ch=getchar();
    return num*f;	
}
inline void write(int x){
    if(x>9)write(x/10);
    putchar(x%10+48);x/=10;
} 
inline void swap(int* a,int* b){int t = *a;*a=*b;*b=t;}

int anc[MAXN][20];
int d[MAXN],dis[MAXN],head[MAXN];

struct Node{
    int next,v,w;
}G[MAXN<<1];

int N,M;
int tot = 0;
inline void add(int u,int v,int w){
    G[++tot].v=v;G[tot].w=w;G[tot].next=head[u];head[u]=tot;
}

inline void dfs(int rt,int fa){
    for(register int i=head[rt];i;i=G[i].next){
        int v = G[i].v;if(v==fa)continue;
        d[v]=d[rt]+1;anc[v][0]=rt;dis[v]=G[i].w^dis[rt];
        dfs(v,rt);
    }
}

inline void find_Node_father(){
    for(register int j=1;j<=17;++j)
    for(register int i=1;i<=N;++i)anc[i][j]=anc[anc[i][j-1]][j-1];
}

inline int LCA(int u,int v){
    if(d[u]<d[v])swap(&u,&v);
    for(register int i=17;i>=0;--i)
        if(d[anc[u][i]]<=d[v])u=anc[u][i];
    if(u==v)return u;
    for(register int i=17;i>=0;--i)
        if(anc[u][i]!=anc[v][i])u=anc[u][i],v=anc[v][i];
    return anc[u][0];
}

int main(){
    

    
    N = read();
    
    for(register int i=1;i<N;++i){
        int u,v,w;
        u=read();v=read();w=read();
        add(u,v,w);add(v,u,w);
    }
    
    dis[1]=0;d[1]=0;
    dfs(1,0);
    find_Node_father();
    
    M = read();
    
    
    for(register int i=0;i<M;++i){
        int u=read();int v=read();
        int lca = LCA(u,v);
        write((dis[lca]^dis[u])^(dis[lca]^dis[v]));putchar('\n');
    }
    return 0;
}
posted @ 2018-02-22 14:18  Neworld1111  阅读(122)  评论(0编辑  收藏  举报