UVALive 7291 Kinfolk(最近公共祖先)

  题目中的描述就很最近公共祖先,再说其实这个题并不难,就是麻烦点(代码其实可以化简的),我写的判定比较多。

  方法;求出两者的最近公共祖先lca,在求出两者到lca的距离

  分析:给出a和b,如果LCA(a,b) == a或者b,那他们肯定是窒息的,是父子,爷孙之类的关系。

     如果LCA(a,b)> a 和 b,假如说a的辈分高(使用深度代表辈分),且disa = 1,那么他们是叔叔,侄子之类的关系

     再者就是堂姐堂弟的关系了,代码里解释的比较详细,代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 32767
struct Node
{
    int l,r,pa,deep;
} node[N+10];
void dfs(int x,int d)
{
    if(x > N) return;
    node[x].l = x*2+1;
    node[x].r = x*2+2;
    node[x].deep = d;
    if(x==0) node[x].pa = x;
    else if(x%2==0) node[x].pa = x/2-1;
    else node[x].pa = x/2;
    dfs(node[x].l,d+1);
    dfs(node[x].r,d+1);
}
int LCA(int a,int b)
{
    while(node[a].deep > node[b].deep)
    {
        a = node[a].pa;
    }
    while(node[b].deep > node[a].deep)
    {
        b = node[b].pa;
    }
    while(a != b)
    {
        a = node[a].pa;
        b = node[b].pa;
    }
    return a;
}
int main()
{
//    freopen("A.in.cpp","r",stdin);
    dfs(0,1);///预处理每一个节点的父亲和深度
    int a,b,lca,disa,disb;
    string tmp;
    char gender;
    while(~scanf("%d %d %c",&a,&b,&gender))
    {
        if(a==-1 && b==-1) break;
        lca = LCA(a,b);///求出lca和距离
        disa = node[a].deep - node[lca].deep;
        disb = node[b].deep - node[lca].deep;
//        printf("LCA(%d,%d) = %d\n",a,b,lca);
//        printf("lca - deep = %d\n",node[lca].deep);
//        printf("disa = %d  disb = %d\n",disa,disb);
        if(a == b) printf("self\n");
        else if(disa == disb && disa == 1)///姐弟关系
        {
            if(gender == ‘F‘) printf("sister\n");
            else printf("brother\n");
        }
        else if(lca == a)///直系关系
        {
            if(gender == ‘F‘) tmp = "daughter";
            else tmp = "son";
            if(disb == 1)
                cout<<tmp<<endl;
            else if(disb == 2) cout<<"grand"<<tmp<<endl;
            else if(disb == 3) cout<<"great-grand"<<tmp<<endl;
            else if(disb == 4) cout<<"great-great-grand"<<tmp<<endl;
            else printf("kin\n");
        }
        else if(lca == b)
        {
            if(gender == ‘F‘) tmp = "mother";
            else tmp = "father";
            if(disa == 1)
                cout<<tmp<<endl;
            else if(disa == 2) cout<<"grand"<<tmp<<endl;
            else if(disa == 3) cout<<"great-grand"<<tmp<<endl;
            else if(disa == 4) cout<<"great-great-grand"<<tmp<<endl;
            else printf("kin\n");
        }
        else if(node[a].pa == lca && node[a].deep < node[b].deep)///叔侄关系
        {
            if(gender == ‘F‘) tmp = "niece";
            else tmp = "nephew";
            if(disb == 2)
                cout<<tmp<<endl;
            else if(disb == 3) cout<<"grand"<<tmp<<endl;
            else if(disb == 4) cout<<"great-grand"<<tmp<<endl;
            else if(disb == 5) cout<<"great-great-grand"<<tmp<<endl;
            else printf("kin\n");
        }
        else if(node[b].pa == lca && node[a].deep > node[b].deep)
        {
            if(gender == ‘F‘) tmp = "aunt";
            else tmp = "uncle";
            if(disa == 2)
                cout<<tmp<<endl;
            else if(disa == 3) cout<<"grand"<<tmp<<endl;
            else if(disa == 4) cout<<"great-grand"<<tmp<<endl;
            else if(disa == 5) cout<<"great-great-grand"<<tmp<<endl;
            else printf("kin\n");
        }
        else if(disa >= 2 && disb >= 2)///堂姐堂弟
        {
            tmp = "cousin";
            int Max = max(disa,disb);
            int Min = min(disa,disb);
            int cha = Max - Min;///这个差帮助我们判定后代
            if(Min <= 4 && cha <= 3)
            {
                if(Min == 2) cout<<"1st "<<tmp;
                else if(Min == 3) cout<<"2nd "<<tmp;
                else if(Min == 4) cout<<"3rd "<<tmp;
                if(cha == 0) cout<<endl;
                else if(cha == 1) cout<<" once removed"<<endl;
                else if(cha == 2) cout<<" twice removed"<<endl;
                else if(cha == 3) cout<<" thrice removed"<<endl;
            }
            else cout<<"kin"<<endl;
        }
        else cout<<"kin"<<endl;
    }
    return 0;
}
时间: 2024-11-05 09:14:00

UVALive 7291 Kinfolk(最近公共祖先)的相关文章

【洛谷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++)//

LCA(最近公共祖先)--tarjan离线算法 hdu 2586

HDU 2586 How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11320    Accepted Submission(s): 4119 Problem Description There are n houses in the village and some bidirectional roads c

最近公共祖先 LCA Tarjan算法

来自:http://www.cnblogs.com/ylfdrib/archive/2010/11/03/1867901.html 对于一棵有根树,就会有父亲结点,祖先结点,当然最近公共祖先就是这两个点所有的祖先结点中深度最大的一个结点. 0 | 1 /   \ 2      3 比如说在这里,如果0为根的话,那么1是2和3的父亲结点,0是1的父亲结点,0和1都是2和3的公共祖先结点,但是1才是最近的公共祖先结点,或者说1是2和3的所有祖先结点中距离根结点最远的祖先结点. 在求解最近公共祖先为问

最近公共祖先

0. 概要 最近公共祖先,指的是在一颗有根树上,两个点的公共祖先中,深度最大的那个. 最直接的应用是求无权树上两个点的最短距离:$distance(u, v)  = depth(u) + depth(v) - 2depth(lca(u, v))$. 再有其他的应用则以后再提. 1 基于 dfs 序列上 RMQ 的稀疏表解法 首先 dfs 遍历树,如下如图中蓝色箭头的顺序.并记录: 1. 遍历点序列 $euler[] = \{1, 2, 1, 3, 5, 3, 6 ……$ 2. 每个点首次在 eu

LeetCode OJ:Lowest Common Ancestor of a Binary Tree(最近公共祖先)

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w

最近公共祖先(三种算法)

最近研究了一下最近公共祖先算法,根据效率和实现方式不同可以分为基本算法.在线算法和离线算法.下面将结合hihocoder上的题目分别讲解这三种算法. 1.基本算法 对于最近公共祖先问题,最容易想到的算法就是从根开始遍历到两个查询的节点,然后记录下这两条路径,两条路径中距离根节点最远的节点就是所要求的公共祖先. 题目参见 #1062 : 最近公共祖先·一 附上AC代码,由于记录的方式采取的是儿子对应父亲,所以实现的时候有点小技巧,就是对第一个节点的路径进行标记,查找第二个节点的路径时一旦发现访问到