C、Xor Path(LCA模板)

北慕城南 提交于 2020-01-24 01:43:54

题目:C、Xor Path

题解:先求根节点到每个结点的异或值,用pre[x],和pre[y]来表示,假设求结点x和结点y之间最短路径的异或值,pre[x]和pre[y]之间一定会有重合的部分,但是pre[x]^pre[y],就把相同的给抵消了。但是他们相同的一定会有离他们最近的公共结点 ,需要把这个点保存下来,就用这个点的异或值与他父亲的异或值相异或,就把这个点给保存了。
需要灵活运用倍增。


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10;

ll bit[N];
int v[N],n;
int step[N],f[N][30];
int Fa[N];
int ans[N];//根结点到x的异或值
vector<int>G[N];

/*********************************************************/
//以下是LCA倍增代码
/*********************************************************/
void init(){
    for(int i = 1;i <= n;i++){
        bit[i] = bit[i-1]+(1<<(bit[i-1])==i);
    }
}
void dfs(int u,int fa){//建立倍增关系
    step[u] = step[fa]+1;//深度
    f[u][0] = fa;//具体的倍增关系
    for(int i = 1;(1<<i) <= step[u];i++){
        f[u][i] = f[f[u][i-1]][i-1];
    }
    for(int i = 0;i < G[u].size();i++){
        int x = G[u][i];
        if(x != fa){//不为父亲,继续往下找
            dfs(x,u);
        }
    }
}
int LCA(int x,int y){
    if(step[x] < step[y]) swap(x,y);
    while(step[x] > step[y]){
        x = f[x][bit[step[x]-step[y]]-1];
    }
    if(x == y) return x;
    for(int k = bit[step[x]-1];k >= 0;k--){
        if(f[x][k] != f[y][k]){
            x = f[x][k];
            y = f[y][k];
        }
    }
    return f[x][0];
}
/*********************************************************/
//以上是LCA倍增代码
/*********************************************************/
void DFS(int u,int fa){//求根结点到u的异或值,以及u的父亲
    Fa[u] = fa;
    ans[u] = v[u]^ans[fa];
    for(int i = 0;i < G[u].size();i++){
        int x = G[u][i];
        if(x != fa){
            DFS(x,u);
        }
    }
}
int main(){
    
    int q;
    cin >> n;
    init();
    for(int i = 1;i <= n;i++){
        scanf("%d",v+i);
    }
    for(int i = 1;i < n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    dfs(1,0);
    DFS(1,0);
    cin >> q;
    while(q--){
        int x,y;
        scanf("%d%d",&x,&y);
        int c = LCA(x,y);
        int d = Fa[c];
    //    cout<<c<<" "<<d<<endl;

        cout<<(ans[x]^ans[y]^ans[c]^ans[d])<<endl;
    }
    return 0;
}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!