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
",a,b,lca);
//        printf("lca - deep = %d
",node[lca].deep);
//        printf("disa = %d  disb = %d
",disa,disb);
        if(a == b) printf("self
");
        else if(disa == disb && disa == 1)///姐弟关系
        {
            if(gender == 'F') printf("sister
");
            else printf("brother
");
        }
        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
");
        }
        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
");
        }
        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
");
        }
        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
");
        }
        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;
}
原文地址:https://www.cnblogs.com/jifahu/p/5746042.html