C、Xor Path(LCA模板)

題目: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;
}

發佈了335 篇原創文章 · 獲贊 25 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章