14932. Lowest Common Ancestor

 

A tree is an undirected graph in which any two vertices are connected by exactly one simple path. In other words, any connected graph without cycles is a tree. - Wikipedia

The lowest common ancestor (LCA) is a concept in graph theory and computer science. Let t be a rooted tree with n nodes. The lowest common ancestor is defined between two nodes v and w as the lowest node in t that has both v and w as descendants (where we allow a node to be a descendant of itself). – Wikipedia

Your task in this problem is to find the LCA of any two given nodes v and w in a given tree t.

 

Input. The first line will be the number of test cases. Each test case will start with a number n (1 n 1000) the number of nodes in the tree. Nodes are numbered from 1 to n. The next n lines each one will start with a number m (0 m 999) the number of child nodes of the n-th node, followed by m numbers the child nodes of the n-th node. The next line will be a number q (1 q 1000) the number of queries you have to answer for the given tree t. The next q lines each one will have two number v and w in which you have to find the LCA of v and w in t (1 v, w 1000).

Input will guarantee that there is only one root and no cycles.

 

Output. For each test case print q + 1 lines, The first line will have “Case C:” without quotes where C is the case number starting with 1. The next q lines should be the LCA of the given v and w respectively.

 

Sample Input

Sample Output

1

7

3 2 3 4

0

3 5 6 7

0

0

0

0

2

5 7

2 7

Case 1:

3

1

 

 

ÐÅØÅÍÈÅ

LCA

 

Àíàëèç àëãîðèòìà

Çàäàíî äåðåâî ñ êîðíåì â âåðøèíå 1. Íåîáõîäèìî îòâåòèòü íà LCA çàïðîñû.

 

Ðåàëèçàöèÿ àëãîðèòìà

 

#include <cstdio>

#include <vector>

#define MAX 1001

using namespace std;

 

int n, l, u, v, i, j, q, edges, ts, tests;

vector<int> g[MAX];

int timer, d[MAX], f[MAX];

int up[MAX][10];

 

void dfs (int v, int p = 1)

{

  int i, to;

  d[v] = timer++;

  up[v][0] = p;

  for(i = 1; i <= l; i++)

    up[v][i] = up[up[v][i-1]][i-1];

  for(i = 0; i < g[v].size(); i++)

  {

    to = g[v][i];

    if (to != p) dfs (to, v);

  }

  f[v] = timer++;

}

 

// if a is a parent of b

int Parent(int a, int b)

{

  return (d[a] <= d[b]) && (f[a] >= f[b]);

}

 

int LCA (int a, int b)

{

  if (Parent(a, b)) return a;

  if (Parent(b, a)) return b;

  for (int i = l; i >= 0; i--)

    if (!Parent(up[a][i], b)) a = up[a][i];

  return up[a][0];

}

 

int main(void)

{

  scanf("%d",&tests);

  for(ts = 1; ts <= tests; ts++)

  {

    printf("Case %d:\n",ts);

    scanf("%d",&n);

 

    for(i = 0; i <= n; i++) g[i].clear();

 

    for(i = 1; i <= n; i++)

    {

      scanf("%d",&edges);

      for(j = 0; j < edges; j++) 

      {

        scanf("%d",&v);

        g[i].push_back(v); g[v].push_back(i);

      }   

    }

 

    l = 1;

    while ((1 << l) <= n + 1)  l++;

 

    dfs(1);

 

    scanf("%d",&q);

    for(i = 0; i < q; i++)

    {

      scanf("%d %d",&u,&v);

      printf("%d\n",LCA(u,v));

    }

  }

  return 0;

}