算法复习——LCA模板(POJ1330)

题目:

Description

A rooted tree is a well-known data structure in computer science and engineering. An example is shown below:

 
In the figure, each node is labeled with an integer from {1, 2,...,16}. Node 8 is the root of the tree. Node x is an ancestor of node y if node x is in the path between the root and node y. For example, node 4 is an ancestor of node 16. Node 10 is also an ancestor of node 16. As a matter of fact, nodes 8, 4, 10, and 16 are the ancestors of node 16. Remember that a node is an ancestor of itself. Nodes 8, 4, 6, and 7 are the ancestors of node 7. A node x is called a common ancestor of two different nodes y and z if node x is an ancestor of node y and an ancestor of node z. Thus, nodes 8 and 4 are the common ancestors of nodes 16 and 7. A node x is called the nearest common ancestor of nodes y and z if x is a common ancestor of y and z and nearest to y and z among their common ancestors. Hence, the nearest common ancestor of nodes 16 and 7 is node 4. Node 4 is nearer to nodes 16 and 7 than node 8 is.

For other examples, the nearest common ancestor of nodes 2 and 3 is node 10, the nearest common ancestor of nodes 6 and 13 is node 8, and the nearest common ancestor of nodes 4 and 12 is node 4. In the last example, if y is an ancestor of z, then the nearest common ancestor of y and z is y.

Write a program that finds the nearest common ancestor of two distinct nodes in a tree.

Input

The input consists of T test cases. The number of test cases (T) is given in the first line of the input file. Each test case starts with a line containing an integer N , the number of nodes in a tree, 2<=N<=10,000. The nodes are labeled with integers 1, 2,..., N. Each of the next N -1 lines contains a pair of integers that represent an edge --the first integer is the parent node of the second integer. Note that a tree with N nodes has exactly N - 1 edges. The last line of each test case contains two distinct integers whose nearest common ancestor is to be computed.

Output

Print exactly one line for each test case. The line should contain the integer that is the nearest common ancestor.

Sample Input

2
16
1 14
8 5
10 16
5 9
4 6
8 4
4 10
1 13
6 15
10 11
6 7
10 2
16 3
8 1
16 12
16 7
5
2 3
3 4
3 1
1 5
3 5

Sample Output

4
3

Source

Taejon 2002

方法:

LCA模板

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
const int N=30010;
vector<int>p[N];
bool visit[N];
int deep[N],g[N][32];
int t,a,b,n;

inline void clear()
{
  memset(g,0,sizeof(g));
  memset(p,0,sizeof(p));
  memset(deep,0,sizeof(deep));
  memset(visit,false,sizeof(visit));
}

inline void dfs(int u)
{
  for(int i=0;i<p[u].size();i++)
  {
    int v=p[u][i];
    if(g[u][0]==v)  continue;
    g[v][0]=u;
    deep[v]=deep[u]+1;
    dfs(v);
  }
}

inline int lca(int a,int b)
{
  int i;
  if(deep[a]<deep[b])  swap(a,b);
  for(i=0;(1<<i)<=deep[a];i++);
  i--;
  for(int j=i;j>=0;j--)
  {
    if(deep[a]-(1<<j)>=deep[b])
      a=g[a][j];
  }
  if(a==b)  return a;
  for(i=31;i>=0;i--)
  {
    if(g[b][i]!=g[a][i])
    {
      b=g[b][i];
      a=g[a][i];
    }
  }
  return g[a][0];
}

int main()
{
  //freopen("a.in","r",stdin);
  //freopen("a.out","w",stdout);
  scanf("%d",&t);
  for(int i=1;i<=t;i++)
  {
    clear();
    int u,v;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
      scanf("%d%d",&u,&v);
      p[u].push_back(v);
      visit[v]=true;
    }
    for(int i=1;i<=n;i++)
    {
      if(visit[i]==false)
      {
        dfs(i);
        break;
      }
    }
    for(int i=1;i<32;i++)
      for(int j=1;j<=n;j++)
        g[j][i]=g[g[j][i-1]][i-1];
    scanf("%d%d",&a,&b);
    cout<<lca(a,b)<<endl;
  }
  return 0;
}
时间: 2024-10-13 01:04:42

算法复习——LCA模板(POJ1330)的相关文章

算法复习——网络流模板(ssoj)

题目: 题目描述 有 n(0<n<=1000)个点,m(0<m<=1000)条边,每条边有个流量 h(0<=h<35000),求从点 start 到点 end 的最大流. 输入格式 第一行:4 个整数,分别是 n,m,start,end .接下来有 m 行,每行四个三个整数 a,b,h,分别表示 a 到 b,流量为 h 的一条边. 输出格式 输出从点 start 到点 end 的最大流. 样例数据 1 输入 [复制] 7 14 1 7 1 2 5 1 3 6 1 4 5

hdu 2586 LCA模板题(离线算法)

http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B&quo

算法复习计划

写在前面 随着四月的到来, 离省选越来越近了. 从NOIP到现在, 学到了很多很多东西, 有的学的比较深入, 有的只是略知一二 从明天开始, 进行针对省选的算法复习计划. 省选前完成. 重点是对算法的理解和应用, 还会注重模板习惯的养成 计划内容 1. 数据结构 一直觉得我数据结构学的还可以, 不过列出来发现会的也没多少. 少就少吧, 省选够用就行... 线段树 树状数组 并查集 哈希表 STL treap splay 树链剖分 主席树(可忽略) 字符串(KMP, 后缀数组) 2. 图论 掌握经

C语言排序算法复习

排序算法有很多种,这里在复习和分析的基础上,做一个自己的总结: 首先要知道有哪些排序算法,google一下,有云C语言7大经典排序算法(也有8大).主要包括冒泡排序,快速排序,选择排序,插入排序,希尔排序,归并排序,堆排序,8大的还有基数排序.各有各的版本,代码写法也各不相同.所以这里以整理思路为先,代码只是作为自己的一个备份. 搞清楚的概念:稳定排序和不稳定排序,就看序列中两个值相等的数,排完序之后的相对位置是否改变,如果改变了就不稳定. 内部排序和外部排序,只用到内存即可完成排序的就叫内部排

HDU 5296 Annoying problem(LCA模板+树的dfs序心得)

Problem Description Coco has a tree, whose nodes are conveniently labeled by 1,2,-,n, which has n-1 edge,each edge has a weight. An existing set S is initially empty. Now there are two kinds of operation: 1 x: If the node x is not in the set S, add n

摘:数据结构各种算法实现(C++模板)

目  录 1.顺序表. 1 Seqlist.h 1 Test.cpp 6 2.单链表. 8 ListNode.h 8 SingleList.h 10 test.cpp 20 3.双向链表. 22 NodeList.h 22 DoubleList.h 24 Test.cpp 34 4.循环链表. 36 ListNode.h 36 CircularList.h 37 Test.cpp 47 5.顺序栈. 49 SeqStack.h 49 Test.cpp 54 6.链式栈. 55 StackNode

排序算法复习

排序算法复习 作者:vpoet mails:[email protected] 注:转载请注明出处 #include <iostream> #include <windows.h> using namespace std; void Bubble_Sort(int UnSort[],int length); void Select_Sort(int UnSort[],int length); void Insert_Sort(int UnSort[],int length); vo

HDU 2586 How Far Away?(Tarjan离线算法求lca)

题意:给定一棵树n个节点m个询问,每次询问两个节点之间的距离. 思路:Tarjan离线算法求lca. 这题一开始交了n发一直爆栈.......百度了一下大概说的是这样hdu用的是windows服务器所以栈大小极其坑爹,稍微深一点的递归就会爆栈(正式比赛一般不会爆) 解决方法就是加一句#pragma comment(linker, "/STACK:1024000000,1024000000") 用c++交就好.....当然这只是针对比较坑爹oj来说的取巧的方法 #include<c

一般排序算法总结与模板

一般排序算法总结与模板 主要包括冒泡.插入.合并排序和两种二分查找的实现. 冒泡排序: 插入排序: 合并排序: #include <stdio.h> #include <stdlib.h> #include <errno.h> int a[]={223, 34, 23, 2, 21, 55, 87, 533 , 213, 111}; //int a[]={2, 21, 23, 34, 55, 87, 111, 213, 223, 533}; //int a[]={533