1. 程式人生 > >SPOJ:Ada and Orange Tree (LCA+Bitset)

SPOJ:Ada and Orange Tree (LCA+Bitset)

max nod oranges 節點 ++ rst possible ota XA

Ada the Ladybug lives near an orange tree. Instead of reading books, she investigates the oranges. The oranges on orange tree can be in up to 5*50 Shades of Orange. She walks from orange to orange, examining different properties of orange tree. The oranges are connected by branches. There is more oranges then branches, yet it is still possible to get from any orange to any other orange [through branches]. The tree is rooted.

Ada has many questions in following form: She goes from orange A to orange B (by shortest path) and is interested in total number different Shades of Orange among all subtrees of all edges on shortest path.

Input

The first line of input consists of 1 ≤ T ≤ 100, the number of test-cases.

The first line of each test case contains three integers 1 ≤ N, Q ≤ 4.5*105

, 0 ≤ R < N, the number of oranges, the number of questions and number of root.

Next line contains N integers 1 ≤ Si ≤ 250, the shade of orange of orange i.

Next N-1 lines contains two integers 0 ≤ I, J < N, I ≠ J , the numbers of oranges which are connected by branch.

Next Q lines contains two integers 0 ≤ A, B < N

, the path Ada is interested about.

The sum of all N and all Q among all test-cases won‘t exceed 106

Output

For each question answer the number of shades in all subtrees of all nodes on shortest path from A to B.

Example Input

1
10 7 1
1 2 1 4 5 6 6 8 9 9
0 9
9 3
3 4
4 6
4 5
4 8
1 3
1 2
2 7
4 4
8 6
0 6
7 0
7 2
0 0
2 3

Example Output

3
3
5
7
2
1
7

題意:給定一棵樹,每個節點有一種顏色的橘子;Q次詢問,每次詢問,給出u、v,回答u到v的最短路徑上的節點的子樹一共有多少種顏色的橘子。

思路:其實就是問最小公共祖先LCA的子樹的顏色種類。因為顏色只有250種,我們DFS時就用Bitset記錄子樹的顏色種類數。

#include<bitset>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=450010;
int Laxt[maxn],Next[maxn<<1],To[maxn<<1];
int fa[maxn][20],dep[maxn],N,Q,rt,cnt;
bitset<251>S[maxn];
void init()
{
    for(int i=1;i<=N;i++) S[i].reset();
    for(int i=1;i<=N;i++) Laxt[i]=0; 
    memset(Laxt,0,sizeof(Laxt));
    cnt=0;
}
void add(int u,int v){
    Next[++cnt]=Laxt[u];
    Laxt[u]=cnt;
    To[cnt]=v;
}
void dfs(int u,int f){
    fa[u][0]=f; dep[u]=dep[f]+1;
    for(int i=Laxt[u];i;i=Next[i]){
        if(To[i]!=f){
          dfs(To[i],u);
          S[u]|=S[To[i]];
        }
    }
}
void RMQ()
{
    for(int i=1;i<20;i++)
     for(int j=1;j<=N;j++)
      fa[j][i]=fa[fa[j][i-1]][i-1];
}
int LCA(int u,int v){
    if(dep[u]<dep[v]) swap(u,v);
    for(int i=19;i>=0;i--)
      if(dep[fa[u][i]]>=dep[v])
        u=fa[u][i];
    if(u==v) return u;
    for(int i=19;i>=0;i--)
      if(fa[u][i]!=fa[v][i])
        u=fa[u][i],v=fa[v][i];
    return fa[u][0];
}
int main()
{
    int T,x,u,v,lca;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&N,&Q,&rt);
        rt++; init();
        for(int i=1;i<=N;i++){
            scanf("%d",&x);
            S[i][x]=1;
        }
        for(int i=1;i<N;i++){
            scanf("%d%d",&u,&v);
            u++; v++;
            add(u,v); add(v,u);
        }
        dfs(rt,0); RMQ();
        while(Q--){
            scanf("%d%d",&u,&v);
            u++; v++;
            lca=LCA(u,v);
            printf("%d\n",S[lca].count());
        }
    }
    return 0;
}

SPOJ:Ada and Orange Tree (LCA+Bitset)