poj1330-----------关于公共祖先的问题

关于公共祖先的问题分类:

这类问题有多种解法和类型,根据题目给出的信息去判断使用哪一种

1、给你树,只支持从父亲找儿子,不支持儿子找父亲,最后要求最近公共祖先,使用dfs或者分治

2、支持儿子找父亲,求最近公共祖先,逆序,从儿子找到底,然后比较(具体看本题代码,说不清)

3、不给树,求是否有共同祖先,并查集

4、还有离线、倍增等方法、

本题属于第二种:

1、从儿子找到底,把两条路径都记录下来

2、从后往前比对两条路径,从那里开始不一样,前一个就是最近的公共祖先

3、注意需要把自己也放进路径中,因为自己可能已经是别人的父亲了

4、使用map存放儿子-》父亲的关系比较好用,因为一个孩子只能有一个父亲。

代码如下:

import java.util.HashMap;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int testCase = cin.nextInt();
        for (int i = 0; i < testCase; i++){
            int n = cin.nextInt();
            HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
            for (int j = 0; j < n-1; j++){
                int parent = cin.nextInt();
                int child = cin.nextInt();
                map.put(child,parent);
            }
            int nodeOne = cin.nextInt();
            int nodeTwo = cin.nextInt();
            System.out.println(nca(nodeOne, nodeTwo, map, n));
        }
    }

    private static int nca(int nodeOne, int nodeTwo, HashMap<Integer,Integer> map, int maxLength){
        int[] nodeOneArray = new int[maxLength];
        nodeOneArray[0] = nodeOne;
        int nodeOneIndex = 1;
        while (map.containsKey(nodeOne)){
            nodeOneArray[nodeOneIndex] = map.get(nodeOne);
            nodeOne = nodeOneArray[nodeOneIndex];
            nodeOneIndex++;
        }

        int[] nodeTwoArray = new int[maxLength];
        nodeTwoArray[0] = nodeTwo;
        int nodeTwoIndex = 1;
        while (map.containsKey(nodeTwo)){
            nodeTwoArray[nodeTwoIndex] = map.get(nodeTwo);
            nodeTwo = nodeTwoArray[nodeTwoIndex];
            nodeTwoIndex++;
        }

        nodeOneIndex--;
        nodeTwoIndex--;
        while (nodeOneArray[nodeOneIndex] == nodeTwoArray[nodeTwoIndex]){
            nodeOneIndex--;
            nodeTwoIndex--;
            if (nodeOneIndex == -1){
                return nodeOneArray[nodeOneIndex+1];
            } else if (nodeTwoIndex == -1){
                return nodeTwoArray[nodeTwoIndex+1];
            }
        }
        return nodeOneArray[nodeOneIndex+1];
    }
}
时间: 2024-12-12 19:20:13

poj1330-----------关于公共祖先的问题的相关文章

POJ1330 Nearest Common Ancestors【最近公共祖先】【Tarjan-LCA算法】

Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 19636Accepted: 10412 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

poj1330 lca 最近公共祖先问题学习笔记

首先推荐两个博客网址: http://dongxicheng.org/structure/lca-rmq/ http://scturtle.is-programmer.com/posts/30055.html [转]tarjan算法的步骤是(当dfs到节点u时): 1 在并查集中建立仅有u的集合,设置该集合的祖先为u 1 对u的每个孩子v:    1.1 tarjan之    1.2 合并v到父节点u的集合,确保集合的祖先是u 2 设置u为已遍历 3 处理关于u的查询,若查询(u,v)中的v已遍

LCA最近公共祖先(POJ1330)

题目链接:http://poj.org/problem?id=1330 解题报告: 先将一个子节点,深搜每一个根节点,并标记. 然后深索另一个子节点,当发现访问过了,就找到了最近的公共祖先. #include <iostream> #include <stdio.h> #include <string.h> using namespace std; const int maxn = 10005; bool vis[maxn]; int father[maxn]; int

POJ1330 Nearest Common Ancestors(最近公共祖先)(tarjin)

A - Nearest Common Ancestors Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%lld & %llu Submit Status Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below: In the figu

POJ-1330&amp;HDU-2586 最近公共祖先(不带权+带权)树剖式写法求LCA

其实敲树剖敲多了就会手敲,然后就发现其实树剖也是可以求LCA的,根据树剖的经验,我们两遍dfs后关于询问l,r的情况我们就开始跳链,当l,r处于同一个链的时候返回深度较小的那个点就好了,这里给个例题: 题目链接:http://poj.org/problem?id=1330 Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown

LCA 算法学习 (最近公共祖先)poj 1330

poj1330 在求解最近公共祖先为问题上,用到的是Tarjan的思想,从根结点开始形成一棵深搜树,处理技巧就是在回溯到结点u的时候,u的子树已经遍历,这时候才把u结点放入合并集合中,这样u结点和所有u的子树中的结点的最近公共祖先就是u了,u和还未遍历的所有u的兄弟结点及子树中的最近公共祖先就是u的父亲结点.这样我们在对树深度遍历的时候就很自然的将树中的结点分成若干的集合,两个集合中的所属不同集合的任意一对顶点的公共祖先都是相同的,也就是说这两个集合的最近公共祖先只有一个.时间复杂度为O(n+q

【洛谷P3379】【模板】最近公共祖先(LCA)

题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每行包含两个正整数x.y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树). 接下来M行每行包含两个正整数a.b,表示询问a结点和b结点的最近公共祖先. 输出格式: 输出包含M行,每行包含一个正整数,依次为每一个询问的结果. 输入输出样例 输入样例#1: 5 5 4 3 1 2 4 5

50、树中两个节点的公共祖先

详细的询问: 1.该树是二叉查找树? 最近公共祖先----二叉查找树:(http://www.lintcode.com/problem/lowest-common-ancestor/) 思路:利用左子树特点:左子树 < 根 <= 右,输入节点跟根节点比较,都小于,在左子树,都大约右子树,递归的去遍历:找到当前节点在两个输入大小之间,当前节点就是. 递归和非递归 public class Solution { public TreeNode lowestCommonAncestor(TreeNo

[最近公共祖先] POJ 3728 The merchant

The merchant Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 4556   Accepted: 1576 Description There are N cities in a country, and there is one and only one simple path between each pair of cities. A merchant has chosen some paths and w

lca最近公共祖先(st表)

大体思路 1.求出每个元素在树中的深度 2.用st表预处理的方法处理出f[i][j],f[i][j]表示元素i上方第2^j行对应的祖先是谁 3.将较深的点向上挪,直到两结点的深度相同 4.深度相同后,祖先可能就在上方,再走几步就到了,于是两个点同时向上移 具体的方法和代码贴在下面 ↓ 具体来看 1.求出每个元素在树中的深度 //求每个节点在树中的深度 void dfs(int pos,int pre)//pre是pos的父节点 { for(int i=0;i<v[pos].size;i++)//