首页 > 试题广场 >

找出直系亲属

[编程题]找出直系亲属
  • 热度指数:8216 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
    如果A,B是C的父母亲,则A,B是C的parent,C是A,B的child,如果A,B是C的(外)祖父,祖母,则A,B是C的grandparent,C是A,B的grandchild,如果A,B是C的(外)曾祖父,曾祖母,则A,B是C的great-grandparent,C是A,B的great-grandchild,之后再多一辈,则在关系上加一个great-。

输入描述:
    输入包含多组测试用例,每组用例首先包含2个整数n(0<=n<=26)和m(0<m<50), 分别表示有n个亲属关系和m个问题, 然后接下来是n行的形式如ABC的字符串,表示A的父母亲分别是B和C,如果A的父母亲信息不全,则用-代替,例如A-C,再然后是m行形式如FA的字符串,表示询问F和A的关系。
    


输出描述:
    如果询问的2个人是直系亲属,请按题目描述输出2者的关系,如果没有直系关系,请输出-。
    具体含义和输出格式参见样例.
示例1

输入

3 2
ABC
CDE
EFG
FA
BE

输出

great-grandparent
-
一道考察并查集的题,被我画图+模拟强行暴力了,定义了个结构体数组,数组下标就是当前处理的字符,每个元素中fa代表父亲,为0,ma代表母亲为1。找了找规律,A了。需要注意的是,parent和child要根据输入判断情况输出,一开始没看懂题,以为都是parent。规律有5种情况,花了两个小时...
#include <bits/stdc++.h>
using namespace std;

const int MAXN = 26;

struct S{
    int fa;
    int ma;
};

S arr[MAXN];

int main()
{
    int n, m;
    while(cin >> n >> m){
        getchar();
        int val = 0;                        // 标记A--这种特殊情况,这种就不把val加1了
        for(int i = 0; i < n; ++i){
            string str;
            getline(cin, str);
            int a, b, c;
            a = str[0] - 'A';
            arr[a].fa = val;            //举个例子,输入ABC,A就为00
            arr[a].ma = val;
            if(str[1] != '-'){
               b = str[1] - 'A';
               arr[b].fa = val+1;     //B为10,0代表B是A的fa,A下一行的左
               arr[b].ma = 0;
            }

            if(str[2] != '-'){
               c = str[2] - 'A';    //C为11,1代表C是A的ma,也就是A下一行的右
               arr[c].fa = val+1;     //依次类推,直到输入结束
               arr[c].ma = 1;
            }
            if(str[1] == '-' && str[2] == '-'){
                val--;  //看不懂的按照输入和我的代码画个图就明白了 
            }        //如果某行输入为X--,那下一行输入要接着这行的上一行,不能让val加1,不然后面都会加1,画图就懂了
            val++;                
        }
        for(int i = 0; i < m; ++i){
            string st;
            getline(cin, st);
            int x, y;
            x = st[0] - 'A';
            y = st[1] - 'A';
            if(arr[x].fa < arr[y].fa){
            S m = arr[x].fa > arr[y].fa ? arr[x] : arr[y];
            S n = arr[x].fa > arr[y].fa ? arr[y] : arr[x];
            int k;
            if(m.fa == m.ma && m.fa != 0){
                m.ma = 1;
            }
            if(n.fa == n.ma && n.fa != 0){
                n.ma = 1;
            }
            if(n.fa == 0 && n.ma == 0){
                k = m.fa - n.fa;
                if(k == 1){
                    cout << "child" << endl;
                }
                else if(k == 2){
                    cout << "grandchild" << endl;
                }
                else{
                    k = k - 2;
                    while(k >= 1){
                        cout << "great-";
                        k--;
                    }
                    cout << "grandchild" << endl;
                }
            }
            else if(m.fa != n.fa && m.ma == 0 && n.ma == 0){
                cout << "-" << endl;
            }
            else if(m.fa != n.fa && m.ma == 1 && n.ma == 0){
                cout << "-" << endl;
            }
            else if(m.fa == n.fa){
                cout << "-" << endl;
            }
            else{
                k = m.fa - n.fa;
                if(k == 1){
                    cout << "child" << endl;
                }
                else if(k == 2){
                    cout << "grandchild" << endl;
                }
                else{
                    k = k - 2;
                    while(k >= 1){
                        cout << "great-";
                        k--;
                    }
                    cout << "grandchild" << endl;
                }
            }
        }
        else if(arr[x].fa > arr[y].fa){
            S m = arr[x].fa > arr[y].fa ? arr[x] : arr[y];
            S n = arr[x].fa > arr[y].fa ? arr[y] : arr[x];
            int k;
            if(m.fa == m.ma && m.fa != 0){
                m.ma = 1;
            }
            if(n.fa == n.ma && n.fa != 0){
                n.ma = 1;
            }
            if(n.fa == 0 && n.ma == 0){
                k = m.fa - n.fa;
                if(k == 1){
                    cout << "parent" << endl;
                }
                else if(k == 2){
                    cout << "grandparent" << endl;
                }
                else{
                    k = k - 2;
                    while(k >= 1){
                        cout << "great-";
                        k--;
                    }
                    cout << "grandparent" << endl;
                }
            }
            else if(m.fa != n.fa && m.ma == 0 && n.ma == 0){
                cout << "-" << endl;
            }
            else if(m.fa != n.fa && m.ma == 1 && n.ma == 0){
                cout << "-" << endl;
            }
            else if(m.fa == n.fa){
                cout << "-" << endl;
            }
            else{
                k = m.fa - n.fa;
                if(k == 1){
                    cout << "parent" << endl;
                }
                else if(k == 2){
                    cout << "grandparent" << endl;
                }
                else{
                    k = k - 2;
                    while(k >= 1){
                        cout << "great-";
                        k--;
                    }
                    cout << "grandparent" << endl;
                }
            }
        }
        else{
            cout << "-" << endl;
        }
        }
    }
    return 0;
}


编辑于 2020-03-25 12:50:09 回复(0)
思路参考的上面保洁大佬,不过求层数感觉还是层次遍历方便点
#include <iostream>
#include <queue>
using namespace std;

const int maxn=100;
struct node
{
	int f,m;
	int level;
	node()
	{
		f=m=-1;
	}
}L[maxn];
int levelorder(int a,int b,int flag)
{
	queue<int> q;
	L[a].level=1;
	q.push(a);
	while(!q.empty())
	{
		int x=q.front();
		if(x==b)
		{
			int d=L[b].level-L[a].level;
			while(d>2)
			{
				cout<<"great-";
				d--;
			}
			if(d==2)	cout<<"grand";
			if(flag)	cout<<"child\n";
			else	cout<<"parent\n";
			return 1;
		}
		q.pop();
		if(L[x].f!=-1)
		{
			int f=L[x].f;
			L[f].level=L[x].level+1;
			q.push(f);
		}
		if(L[x].m!=-1)
		{
			int m=L[x].m;
			L[m].level=L[x].level+1;
			q.push(m);
		}
	}
	return 0;
}
int main()
{
	int m,n;
	while (cin>>n>>m)
	{
		for (int i=0;i<n;++i)
		{
			char c,f,m;
			cin>>c>>f>>m;
			if(f!='-')	L[c-'A'].f=f-'A';
			if(m!='-')	L[c-'A'].m=m-'A';
		}
		for (int i=0;i<m;++i)
		{
			char a,b;
			cin>>a>>b;
			if(levelorder(a-'A',b-'A',1))	 continue;
			else  if(levelorder(b-'A',a-'A',0)==0)  cout<<"-\n";
		}
	}
	return 0;
}


发表于 2020-01-13 10:51:31 回复(0)
#include<stdio.h>
#include<map>
using namespace std;
map<char,char> fa;
int query(char,char);
void print(int,int);
int main(){
    int n,m,i;
    //freopen("input.txt","r",stdin);
    while(scanf("%d%d",&n,&m)!=EOF&&n&&m){
        char in[100];
        fa.clear();
        for(i=0;i<n;i++){
            scanf("%s",in);
            fa[in[1]]=in[0],fa[in[2]]=in[0];
        }
        for(i=0;i<m;i++){
            scanf("%s",in);
            int deep1=query(in[0],in[1]);
            int deep2=query(in[1],in[0]);
            if(deep1!=-1) print(deep1,1);
            else if(deep2!=-1) print(deep2,0);
            else printf("-\n");
        }
    }
}
int query(char a,char b){
    if(a==b) return -1;
    int deep=0,flag=0;
    while(b!=a&&fa.count(b)){
        b=fa[b],deep++;
        if(b==a) flag=1;
    }
    if(flag==0) return -1;
    return deep;
}
void print(int x,int flag){
    if(x==1) printf("%s\n",flag==0?"parent":"child");
    else if(x==2) printf("grand%s\n",flag==0?"parent":"child");
    else{
        for(int i=0;i<x-2;i++) printf("great-");
        printf("grand%s\n",flag==0?"parent":"child");
    }
}

发表于 2017-10-27 13:49:07 回复(0)
根据题意,这个题只应用到26个大写字母作为关系对象,并且可能存在多个孩子的问题,因此将此题看成对于一张有向图的搜索会比二叉树好一些,通过双向搜索得出二者关系
附代码(有点菜鸡)
#include<iostream>
(720)#include<string>
using namespace std;
struct Re           //自定义保存亲属关系(图的节点定义)
{
	char child;
	char mother;
	char father;

};
Re indexS[27];
int DFS(Re p,char find,int k)           //搜索    深度
{
	if (p.child == find) return k;
	if (p.father == ' '&&p.mother == ' ') return -1;
	
	if (p.mother!=' '&&DFS(indexS[p.mother - 65], find, k + 1) != -1)  return  DFS(indexS[p.mother - 65], find, k + 1);
	else if(p.father!=' ' )
		return DFS(indexS[p.father - 65], find, k + 1);
	else return -1;
}
void Initial()      //初始化节点对象
{
	for (int i = 0; i < 27; i++)
	{
		indexS[i].child = char (i + 65) ;
		indexS[i].father = ' ';
		indexS[i].mother = ' ';
	
	}


}
int main()
{
	int m, n;
	string s;
	while (cin>>m>>n)
	{
		Initial();
		for (int i = 0; i < m; i++)
		{
			cin >> s;
			if(s[1]!='-')
			indexS[s[0] - 65].mother = s[1];
			if (s[2] != '-')
			indexS[s[0] - 65].father = s[2];
		
		}
		
		for (int i = 0; i < n; i++)
		{
			cin >> s;
			if (s[0] == s[1]) cout << "-" << endl;
			else
			{
				int g = DFS(indexS[s[0] - 65], s[1], 0);    //双向搜索
				int k = DFS(indexS[s[1] - 65], s[0], 0);   
				if (k != -1)
				{
					if (k == 1) cout << "parent" << endl;
					else if (k == 2) cout << "grandparent" << endl;
					else
					{
						for (int i = 1; i <= k - 2; i++)   cout << "great-";
						cout << "grandparent" << endl;
					}
			
				}
				else if (g != -1)
				{
					if (g == 1) cout << "child" << endl;
					else if (g == 2) cout << "grandchild" << endl;
					else
					{
						for (int i = 1; i <= g - 2; i++)   cout << "great-";
						cout << "grandchild" << endl;
					}
				}
				else cout << "-" << endl;
			}
		}
	
	
	}
}


编辑于 2020-03-09 22:47:53 回复(4)
提供一个思路,建树,每次从查询节点出发,看是否能找到另一个节点,如果找不到,互换起点再找,两次都找不,说明他俩没有关系
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cctype>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <cstring>
#include <iomanip>
#include <sstream>

using namespace std;

#pragma warning(disable:4996)
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define repr(i, a, b) for(int i = a; i >= (b); --i)
#define trav(a, x) for (auto& a : x)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

const int INF = 0x3f3f3f3f;
struct node{
    char ch;
    struct node *left = nullptr, *right = nullptr;
    node (char c) : ch(c){}
};
int h1 = 0;
void dfs(node* root, node* target, int dep) {
    if (!root)
        return;
    if (root == target)
        h1 = dep;
    dfs(root->left, target, dep + 1);
    dfs(root->right, target, dep + 1);
}
int main(){
    int n, m;
    while (cin >> n >> m) {
        map<char, node*> mp;
        node *root;
        rep(i, 0, n) {
            string s;
            cin >> s;
            if (mp.count(s[0]) == 0)
                mp[s[0]] = new node(s[0]);
            if (s[1] != '-' && mp.count(s[1]) == 0)
                mp[s[1]] = new node(s[1]);
            if (s[2] != '-' && mp.count(s[2]) == 0)
                mp[s[2]] = new node(s[2]);
            if (s[1] != '-')
                mp[s[0]]->left = mp[s[1]];
            if (s[2] != '-')
                mp[s[0]]->right = mp[s[2]];
        }
        rep(i, 0, m) {
            char a, b;
            h1 = 0;
            cin >> a >> b;
            dfs(mp[b], mp[a], 0);
            if (h1 == 0) {
                dfs(mp[a], mp[b], 0);
                h1 = -h1;
            }
            if (h1 == 0) {
                cout << "-" << endl;
            }
            if (h1 > 0) {
                if (h1 == 1)
                    cout << "parent" << endl;
                else if (h1 == 2)
                    cout << "grandparent" << endl;
                else {
                    rep(k, 0, h1 - 2)
                        cout << "great-";
                    cout << "grandparent" << endl;
                }
            }
            if (h1 < 0) {
                if (h1 == -1)
                    cout << "child" << endl;
                else if (h1 == -2)
                    cout << "grandchild" << endl;
                else {
                    rep(k, 0, abs(h1) - 2)
                        cout << "great-";
                    cout << "grandchild" << endl;
                }                
            }
        }
    }
    return 0;
 }



发表于 2022-03-16 16:02:29 回复(0)
#include <iostream>
#include "map"
#include "cmath"
using namespace std;
/*其实可以建立一个二叉树 其根为子孙 叶子为祖先 因为爸妈可以有多个孩子 孩子只有一个亲生爸妈 
用map去存这样的映射 递推查询两者的相对深度即可*/
map<char, char> s2f;/*孩子到父亲 孩子到母亲的映射*/
map<char, char> s2m;

void n2s(string &prefix, int dep){
    /*根据aIsBSon得到的深度 得到前缀*/
    if(dep<= 1){return;
    }else if(dep== 2){prefix= prefix+ "grand";return;
    }else{prefix= prefix+ "great-";n2s(prefix, dep- 1);
    }
}
/*设想A是B的儿子的话 AB的相对深度是多少 返回0表示A不是B的儿子*/
int aIsBSon(char A, char B, int dep){
    if(A== B){return 0;
    }else if(s2f.count(A)== 0&& s2m.count(A)== 0){return -dep;// 负深度用于得到返回值0
    }else{
        int dAF, dAM;
        dAF= dAM= -dep;
        if(s2f.count(A)){dAF= aIsBSon(s2f[A], B, dep+ 1);}
        if(s2m.count(A)){dAM= aIsBSon(s2m[A], B, dep+ 1);}
        return max(dAF, dAM)+ 1;// 将问题规约为A的爸妈为孩子与B的相对深度
    }
}

int main(int argc, char *argv[]) {

    int n, m;
    while(cin>> n>> m){
        for(int i= 0; i< n; i++){
            char s, f, m;cin>> s>> f>> m;
            s2f[s]= f;s2m[s]= m;// 建立映射
        }
        for(int i= 0; i< m; i++){
            char a, b;cin>> a>> b;
            int dep= aIsBSon(a, b, 0);// 
            if(!dep){dep= -1* aIsBSon(b, a, 0);}// A不是B的孩子 B是A的孩子的情况
            string prefix, basic;// 设置前缀 方便将深度转化为输出串
            prefix= "";basic= (dep> 0? "child": (dep< 0? "parent": "-"));
            n2s(prefix, abs(dep));
            cout<< prefix+ basic<< endl;
        }
        s2f.clear();s2m.clear();
    }
    return 0;
}
发表于 2022-03-05 16:01:55 回复(0)
#include<iostream>
using namespace std;
#define MAXN 1000

int son[MAXN];
int num;

void initial(){
    for(int i=0;i<MAXN;i++){
        son[i] = i;
    }
}

bool find(int p,int c){
    if(p == c) return true;
    if(p == son[p]) return false;
    num++;
    return find(son[p],c);
}

int main(){
    int n,m;
    while(cin>>n>>m){
        initial();
        string s;
        while(n--){
            cin>>s;
            if(s[1] == '-' && s[2] == '-') continue;
            if(s[1] == '-') son[s[2]-'A'] = s[0]-'A';
            if(s[2] == '-') son[s[1]-'A'] = s[0]-'A';
            if(s[1] != '-' && s[2] != '-'){
                son[s[1]-'A'] = s[0]-'A';
                son[s[2]-'A'] = s[0]-'A';
            }
        }
        while(m--){
            cin>>s;
            num=0;
            if(find(s[0]-'A',s[1]-'A')){
                if(num == 1) cout<<"parent"<<endl;
                else if(num == 2) cout<<"grandparent"<<endl;
                else{
                    num-=2;
                    while(num--) cout<<"great-";
                    cout<<"grandparent"<<endl;
                }
            }
            else {
                num=0;
                if(find(s[1]-'A',s[0]-'A')){
                    if(num==1) cout<<"child"<<endl;
                    else if(num == 2) cout<<"grandchild"<<endl;
                    else{
                        num-=2;
                        while(num--) cout<<"great-";
                        cout<<"grandchild"<<endl;
                    }
                }
                else cout<<"-"<<endl;
            }
            
        }
        
    }
    return 0;
}

发表于 2021-08-19 17:11:51 回复(0)
def find(x,y):
    ans=1
    global father
    tmp1=father[ord(x) - ord('A')]
    while tmp1!=father[tmp1]:
        if tmp1==ord(y)-ord('A'):
            return ans
        tmp1=father[tmp1]
        ans+=1
    if tmp1 == ord(y) - ord('A'):
        return ans
    return 0

while True:
    try:
        father=[i for i in range(26)]
        n,m=map(int,input().split())
        for i in range(n):
            s=input()
            if s[1]!='-':
                father[ord(s[1])-ord('A')]=ord(s[0])-ord('A')
            if s[2]!='-':
                father[ord(s[2])-ord('A')]=ord(s[0])-ord('A')
        ques=[]
        for i in range(m):
            ques.append(input())
        for i in ques:
            s=i
            x=find(s[0],s[1])
            y=find(s[1],s[0])
            flag=2
            if x>0 and y==0:
                flag=0         #s[0]是高辈分
            if x==0 and y>0:
                flag=1 #s[1]是高辈分
            tmp=max(x,y)
            if tmp==0:
                print('-')
                continue
            if tmp==1:
                if flag==0:
                    print("parent")
                else:
                    print("child")
            elif tmp==2:
                if flag == 0:
                    print('grandparent')
                else:
                    print("grandchild")
            else:
                tmp-=2
                if flag == 0:
                    ans='grandparent'
                else:
                    ans = 'grandchild'
                while tmp:
                    ans='great-'+ans
                    tmp-=1
                print(ans)
    except:
        exit()

发表于 2021-03-16 01:30:35 回复(0)
时间3ms,内穿376KB.
仿造链表的思想。使用一个son数组记录每个点的孩子。relnum函数判断结点之间的辈分关系,print函数用于输出。
#include<cstdio>
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int son[30] = {0};
int num;
int relnum(int a, int b){//判断b是否为a的后代。如果是,返回辈分差,不是,返回0 
	int now = a;//表示当前遍历的结点 
	while(now != 0){//一直循环a到没有儿子 
		if(now == b){//表示a的后代中找到了b,返回辈分差 
			return num;
		}
		num++;
		now = son[now];
	}
	return 0;//没有儿子跳出循环,返回0 
}
void print(int a, int b){//根据辈分差进行输出 
	num = 0;
	int tnum1 = relnum(a, b);//记录ab辈分差差(a的辈分大于b) 
	num = 0;
	int tnum2 = relnum(b, a); 
	if(tnum1 == 0 && tnum2 == 0){
		cout << "-";
	}else if(tnum1 != 0 && tnum2 == 0){//b是a后代 
		for(int i = 2; i < tnum1; i++) cout << "great-";//tnum为2的时候输出一个great
        if(tnum1 == 1) cout << "parent";
        if(tnum1 > 1) cout << "grandparent";
	}else if(tnum2 != 0 && tnum1 == 0){
		for(int i = 2; i < tnum2; i++) cout << "great-";//tnum为2的时候输出一个great
        if(tnum2 == 1) cout << "child";
        if(tnum2 > 1) cout << "grandchild";
	} 
}
int main(){
	int n, m;
	while(cin >> n >> m){
		string s;
		for(int i = 0; i < n; i++){//记录每个人的儿子 
			cin >> s;
			if(isalpha(s[1])) son[s[1]-'A'+1] = s[0]-'A'+1;
			if(isalpha(s[2])) son[s[2]-'A'+1] = s[0]-'A'+1;
		}
		for(int i = 0; i < m; i++){//用于测试 
			cin >> s;
			print(s[0]-'A'+1, s[1]-'A'+1);
			cout << endl;
		}
	}
	return 0;
}


编辑于 2021-02-19 14:05:04 回复(0)
/*
*并查集,child数组记录孩子。
*一对夫妇只有一个孩子,不然这道题用并查集就显然不对。
*/

#include<bits/stdc++.h>

using namespace std;

const int maxn = 1e2;
int child[maxn+5];
int n, m;

void Initial()
{
    for(int i = 0;i < maxn; i++) child[i] = i;
}

void Create(string s)     //建立并查集
{
    for(int i = 1;i <= 2; i++)
    {
        if(s[i] == '-') continue;
        else child[s[i]-'A'] = s[0]-'A';
    }
}

int Find(int f, int c)    //找孩子 
{
    int ans = 1;
    while(child[f] != c && child[f] != f)
    {
        f = child[f]; ans++;
    }
    if(child[f] == f) return -1;   //c  不是   f的孩子
    return ans;     //c  是   f 的孩子
}

int main()
{
    ios::sync_with_stdio(false);
    string s;
    while(cin >> n >> m)
    {
        Initial();
        for(int i = 0;i < n; i++)
        {
            cin >> s; Create(s);
        }
        for(int i = 0;i < m; i++)
        {
            cin >> s; string endstr, str = "";
            int t1 = Find(s[0]-'A', s[1]-'A');
            int t2 = Find(s[1]-'A', s[0]-'A');
            if(t1 == -1 && t2 == -1)
            {
                cout << '-' << '\n'; continue;
            }
            else if(t1 != -1) endstr = "parent";  //数据没说保证FA中F一定是祖辈 ,所以FA各自作为父亲,都要试一试
            else endstr = "child";
            for(int t = max(t1, t2);t > 1; t--)
            {
                if(t == 2) str += "grand";
                else str += "great-";
            }
            cout << str+endstr << '\n';
        }
    }
    return 0;
}

发表于 2021-01-20 17:50:10 回复(0)
#include<iostream>
#include<string>
using namespace std;
int main()
{
	int n, m;
	string input, question;
	char child[26];
	while (cin>>n>>m)
	{
		for (int i = 'A'; i <= 'Z'; i++)
			child[i - 'A'] = '@';//初始每个字母没有孩子

		for (int i = 0; i < n; i++)//输入关系
		{
			cin >> input;
			child[input[1] - 'A'] = input[0];
			child[input[2] - 'A'] = input[0];
		}
		for (int i = 0; i < m; i++)//输入判断
		{
			cin >> question;
			int generation, j;
			for (j = 0; j <= 1; j++)//判断
			{
				char x = question[j];
				generation = 0;
				while (x != question[1-j])
				{
					if (x == '@')
					{
						generation = 0;
						break;
					}
					x = child[x - 'A'];
					generation++;
				}
				if (generation != 0)//已经找出亲属关系
					break;
			}//j只有三种情况,j==0前面是长辈j==1后面是长辈j==2没有直系亲属关系
			if (generation == 1)
				cout << (j == 0 ? "parent" : "child") << endl;
			else if (generation >= 2)
			{
				for (int i = 0; i < generation-2; i++)
					cout << "great-";
				cout << (j == 0 ? "grandparent" : "grandchild") << endl;
			}
			else
				cout << "-" << endl;
		}
	}
	return 0;
}

数组模拟二叉树,不断的找后代
编辑于 2020-06-28 17:14:30 回复(0)
#include <bits/stdc++.h>
using namespace std;

map<char, vector<char>> node;

int find_ship(char a, char b)        //层次遍历
{
	int gap = 1;	
	queue<char> qu;
	for (auto c : node[b])
		qu.push(c);
	while (!qu.empty())
	{
		int qu_size = qu.size();
		for (int i = 0; i < qu_size; i++)
		{
			char res = qu.front();
			qu.pop();
			if (res == a)
				return gap;		
			if (node.find(res) != node.end())
				for (auto c : node[res])
					qu.push(c);
		}
		gap++;
	}
	return 0;
}

int solution(char a, char b)
{
	return find_ship(b, a) - find_ship(a, b); //负数表示parent,正数表示child

}

int main()
{
	int m, n;
	cin >> m >> n;
	char a, b, c;
	for (int i = 0; i < m; i++)
	{
		cin >> a >> b >> c;
		node[a].push_back(b);
		node[a].push_back(c);
	}

	for (int i = 0; i < n; i++)
	{
		cin >> a >> b;
		int gap = solution(a, b);
		if (gap == 0)
			cout << "-" << endl;
		else
		{
			string ship = "child";
			if (gap < 0)
			{
				ship = "parent";
				gap = -gap;
			}
			string front;
			if (gap >= 2)
				front = "grand" + front;
			for (int i = 0; i < gap - 2; i++)
				front = "great-" + front;
			cout << front << ship << endl;
		}
	}
}


发表于 2020-04-29 17:14:36 回复(0)
/*
    这道题我使用的链表思路去做的,因为每个父母只有一个孩子,
所以我这样比较简单易懂,不同于大家二叉树的做法把,而且我是用静态数组实现的

*/

#include<iostream>
(720)#include<cstring>
using namespace std;
char Child[91];
int find(char p,char s){
    int num=1;
    while(Child[p]!=s&&Child[p]!=' '){
        p=Child[p];
        num++;
    }
    if(Child[p]==s)    return num;
    else    return 0;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n,m;
    string relation;
    char c,p;
    while(cin>>n>>m){
        memset(Child,' ',sizeof(Child));
        for(int i=0;i<n;i++){
            cin>>relation;
            if(relation[1]!='-')    Child[relation[1]]=relation[0];
            if(relation[2]!='-')    Child[relation[2]]=relation[0];
        }
        for(int i=0;i<m;i++){
            cin>>relation;
            int x=find(relation[0],relation[1]);
            if(x>0){
                if(x==1)    cout<<"parent"<<endl;
                else{
                    for(int i=x-2;i>0;i--)
                        cout<<"great-";
                    cout<<"grandparent"<<endl;
                }
                continue;
            }
            x=find(relation[1],relation[0]);
            if(x==0)    cout<<"-"<<endl;
            else if(x==1)    cout<<"child"<<endl;
            else{
                for(int i=x-2;i>0;i--)
                        cout<<"great-";
                    cout<<"grandchild"<<endl;
            }
        }
    }
    return 0;
}

编辑于 2020-03-21 22:45:28 回复(0)
/*并查集思想,每个结点存储自己的孩子结点,查找关系时,向下查找。*/
#include<iostream>
using namespace std;
int child[27];
int find(int s,int t){
    int flag=0,count=0,s1=s;
    while(child[s]!=t&&child[s]!=-1){
        ++count;
        s=child[s];
    }
    if(child[s]==t) return count+1;
    count=0;
    s=s1;
    while(child[t]!=s&&child[t]!=-1){
        ++count;
        t=child[t];
    }
    if(child[t]==s) return -(count+1);
    return 0;
}
 int main(){
     int n,m;
     while(cin>>n>>m){
         for(int i=0;i<=26;i++) child[i]=-1;//初始化
         while(n--){
             string s;
             cin>>s;
             int a=s[0]-'A';
             for(int i=1;i<s.length();i++){
                 if(s[i]!='-'){
                     int b=s[i]-'A';
                     child[b]=a;
                 }
             }
         }
         while(m--){
             string s;
             cin>>s;
             int p=s[0]-'A',q=s[1]-'A';//求p和q的关系
             int c=find(p,q);
             if(c==0) cout<<"-"<<endl;
             else if(c>0){
                 if(c==1) cout<<"parent"<<endl;
                 else if(c==2) cout<<"grandparent"<<endl;
                 else{
                     int tmp=c-2;
                     while(tmp--) cout<<"great-";
                     cout<<"grandparent"<<endl;
                 }
             }
             else{
                 c=-c;
                 if(c==1) cout<<"child"<<endl;
                 else if(c==2) cout<<"grandchild"<<endl;
                 else{
                     int tmp=c-2;
                     while(tmp--) cout<<"great-";
                     cout<<"grandchild"<<endl;
                 }
             }
         }
     }
     return 0;
 }



发表于 2020-03-11 14:22:01 回复(0)
//把孩子节点指向父母的看作为有向边,使用floyd算法找出需求两边的最小值
#include <bits/stdc++.h>
using namespace std;
const  int  maxn = 1010;
int   matrix[maxn][maxn];
const  int  INF = 0xffffff;
int   total = 0;
void  floyd()
{
for(int  k=1;k<=total;k++)
{
for(int  i=1; i<=total; i++)
{
for(int  j=1; j<=total; j++)
{

if(matrix[i][j] > matrix[i][k]+matrix[k][j])
{
//printf("matrix[%d][%d] = %d\n",i,j,matrix[i][j]);
//printf("matrix[%d][%d] = %d\n",i,k,matrix[i][k]);
//printf("matrix[%d][%d] = %d\n",k,j,matrix[k][j]);
matrix[i][j] = matrix[i][k]+matrix[k][j];
//printf("***matrix[%d][%d] = %d\n",i,j,matrix[i][j]);
}
}
}
}
}
int   main()
{
int  n,m;
while(cin>>n>>m)
{
fill(matrix[0],matrix[0]+maxn*maxn,INF);
for(int  i=0;i<n;i++)
{
string  s;
cin>>s;
int  data1 = s[0]-'A'+1;
total = max(data1,total);
if(s[1] != '-')
{
int  data2 = s[1]-'A'+1;
total = max(data2,total);
matrix[data2][data1] = 1;
}
if(s[2] != '-')
{
int  data2 = s[2]-'A'+1;
total = max(data2,total);
matrix[data2][data1] = 1;
}
}
//为有向图,确定矩阵的距离
floyd();
//求任意两点间的距离用floyd算法
for(int  o=0;o<m;o++)
{
string  s;
cin>>s;
int   data1 = s[0]-'A'+1;
int   data2 = s[1]-'A'+1;
if(matrix[data1][data2] == INF&&
matrix[data2][data1] == INF)
{
printf("-\n");
}
else
{
int  results = min(matrix[data1][data2],
matrix[data2][data1]);
//printf("results = %d\n",results);
for(int  i=1;i<=results-2;i++)
{
printf("great-");
}
if(results >= 2)
{
printf("grand");
}
if(matrix[data1][data2] == INF)
{
printf("child\n");
//data2能够指向data1时,打印child
}
else
{
printf("parent\n");
//data1能够指向data2时,打印parent
}
}
}
}
return  0;
}


编辑于 2020-03-06 13:20:43 回复(0)
/*法一:
基本思路:一维数组存储父节点信息,采用递归的方式进行搜索
存储方式,类似于并查集的方法采用一个一维数组Tree[N]进行存储。
首先需要把字符映射为编号,A~Z分别对应0~25的数字编号。
由于每一个字母最多会存在两个父节点,因此我们采用数组中
连续的两位来存储其父节点的编号。Tree[0],Tree[1]中存储的是字母
A的父节点信息。
在解决了存储问题之后就可以采用递归的方法去遍历待查询结点的父节点
信息了,如果找到满足的情况则返回搜索的深度。如果碰到了-1则说明不存在关系。
*/

#include<bits/stdc++.h>
#define N 53
using namespace std;
int Tree[N];
int Level=0;

void findLevel(int x,int level,int target){
    if(Tree[x*2]==target||Tree[x*2+1]==target)
        Level=level;
    else{
        if(Tree[x*2]!=-1)
             findLevel(Tree[x*2],level+1,target);
        if(Tree[x*2+1]!=-1)
             findLevel(Tree[x*2+1],level+1,target);
    }
}

int main()
{
    int n,m;
    char a,b,c;
    int child,parent;
    while(cin>>n>>m){
        for(int i=0;i<N;i++)
            Tree[i]=-1;
        for(int i=0;i<n;i++){
            cin>>a>>b>>c;
            if(b!='-')
            Tree[2*(a-'A')]=b-'A';
            if(c!='-')
            Tree[2*(a-'A')+1]=c-'A';
        }
        for(int i=0;i<m;i++){
            cin>>a>>b;
            Level = -1;
            findLevel(a-'A',1,b-'A');
            int l1 = Level;
            Level = -1;
            findLevel(b-'A',1,a-'A');
            int l2 = Level;
            int level = l1>l2?l1:l2;

            if(level==-1)
                cout<<"-"<<endl;
            else if(l1>l2){

                if(level==1){
                    cout<<"child"<<endl;
                }
                else if(level==2){
                    cout<<"grandchild"<<endl;
                }
                else{
                    for(int i=2;i<level;i++)
                        cout<<"great-";
                    cout<<"grandchild"<<endl;
                }
            }
            else if(l2>l1){

                if(level==1){
                    cout<<"parent"<<endl;
                    }
                else if(level==2){
                    cout<<"grandparent"<<endl;
                }
                else{
                    for(int i=2;i<level;i++)
                        cout<<"great-";
                    cout<<"grandparent"<<endl;
                }
            }
            else{
                cout<<"-"<<endl;
            }
        }
    }
    return 0;
}

/*
法二:
后来想了想确实,如果采用两遍搜索的话效率有点低,而且不能改成迭代,那么
其实只需要把搜索的顺序反过来就可以了,那么顺理成章就变成了一颗标准的二叉树
(法一是一颗倒二叉树),那么这样就可以直接套用并查集的迭代函数的模板了,改进
之后效率提升了不少。
*/
#include <iostream>
#define N 27
using namespace std;

int Tree[N];

int findLevel(int x,int target){
    int level=1;
    while(1){
        if(Tree[x]==-1){//没找到
            return -1;
        }
        if(Tree[x]!=target){
            level++;
            x=Tree[x];//查询下一层
        }
        else{
            break;
        }

    }
    return level;
}

int main()
{
    int n,m;
    char a,b,c;
    while(cin>>n>>m){
        for(int i=0;i<N;i++)
            Tree[i]=-1;
        for(int i=0;i<n;i++){
            cin>>a>>b>>c;
            if(b!='-')
            Tree[b-'A']=a-'A';
            if(c!='-')
            Tree[c-'A']=a-'A';
        }

        for(int i=0;i<m;i++){
            cin>>a>>b;

            int l1 = findLevel(a-'A',b-'A');
            int l2 = findLevel(b-'A',a-'A');

            int level = l1>l2?l1:l2;

            if(level==-1)
                cout<<"-"<<endl;

            else if(l2>l1){

                if(level==1){
                    cout<<"child"<<endl;
                }
                else if(level==2){
                    cout<<"grandchild"<<endl;
                }
                else{
                    for(int i=2;i<level;i++)
                        cout<<"great-";
                    cout<<"grandchild"<<endl;
                }
            }
            else if(l1>l2){

                if(level==1){
                    cout<<"parent"<<endl;
                }
                else if(level==2){
                    cout<<"grandparent"<<endl;
                }
                else{
                    for(int i=2;i<level;i++)
                        cout<<"great-";
                    cout<<"grandparent"<<endl;
                }
            }
            else{
                cout<<"-"<<endl;
            }
        }

    }
    return 0;
}

编辑于 2019-04-23 10:41:06 回复(0)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <vector>
#include <queue>
#include <map>
using namespace std;
map<char, vector<char> > mp;
int ans;
int flag; 
void findRoot(char s, char t, int now)
{
    for(int i = 0 ;i<mp[s].size();i++)
    {
        if(mp[s][i] == t)
        {
            flag++;
            ans = now;
            return ;
        }
        else
        {
            findRoot(mp[s][i],t,now+1);
        }
    }
}
int main()
{
    int n,m;
    
    while(cin >> n >> m)
    {
        mp.clear();
        string s; 
        for(int i = 0 ;i<n;i++)
        {
            cin >>s;
            for(int j = 1;j<s.length();j++)
            {
                mp[s[0]].push_back(s[j]);
            }
        }
        for(int i = 0 ;i<m;i++)
        {
            flag = 0 ;
            cin >> s;
            ans = 0;
            findRoot(s[1],s[0],1);
            if(ans == 0)
            {
                flag = 0;
                findRoot(s[0],s[1],1);
                if(ans == 0)
                flag = 0;
                else
                flag = 2;
            }
            if(flag == 0)
            {
                cout << "-" << endl;
                continue;
            }
            else if(flag == 1)
            {
                if(ans == 1)
                {
                    cout << "parent" << endl;
                }
                else if(ans == 2)
                {
                    cout << "grandparent" << endl;
                }
                else
                {
                    for(int i = 0 ; i<ans - 2 ;i++)
                    cout <<"great-";
                    cout <<"grandparent" << endl;
                }
            }
            else if(flag == 2)
            {
                if(ans == 1)
                {
                    cout << "child" << endl;
                }
                else if(ans == 2)
                {
                    cout << "grandchild" << endl;
                }
                else
                {
                    for(int i = 0 ; i<ans - 2 ;i++)
                    cout <<"great-";
                    cout <<"grandchild" << endl;
                }
            }
        }
    }
    return 0;
}

发表于 2019-03-13 22:21:54 回复(0)
#include <stdio.h>
#include <string.h>
#include <stdio.h>

#define MAX 40

char str[10];
int child[300];

int find(char c1,char c2,int time)
{
    if(child[c1]==c2)
    {
        return time;
    }
    if(child[c1]==-1)
    {
        return 0;
    }
    int tmp=find(child[c1],c2,time+1);
    return tmp;
}

int main()
{
    int n,m;
    int i,j;
    while(scanf("%d %d",&n,&m)!=EOF&&(n||m))
    {
        memset(child,-1,sizeof(child));
        for(i=0;i<n;i++)
        {
            scanf("%s",str);
            if(str[1]!='-') child[str[1]]=str[0];
            if(str[2]!='-') child[str[2]]=str[0];
        }
        for(i=0;i<m;i++)
        {
            scanf("%s",str);
            int flag=find(str[0],str[1],1);
            if(flag)
            {
                if(flag==1) printf("parent\n");
                else{
                    for(j=2;j<flag;j++)
                    {
                        printf("great-");
                    }
                    printf("grandparent\n");
                }
                continue;
            }
            flag=find(str[1],str[0],1);
            if(flag)
            {
                if(flag==1) printf("child\n");
                else{
                    for(j=2;j<flag;j++)
                    {
                        printf("great-");
                    }
                    printf("grandchild\n");
                }
                continue;
            }
            else
            {
                printf("-\n");
            }
        }
    }
    return 0;
}

发表于 2018-08-19 20:18:46 回复(0)
//Floyd+有向图
#include <bits/stdc++.h>

using namespace std;
const int MAXN=50;
int dis[MAXN][MAXN];
const int INF=INT_MAX;

int Add(int x,int y)
{
    if(x==INF||y==INF) return INF;
    else return x+y;
}

void Floyd(int n)
{
    for(int k=0;k<MAXN;k++)
    {
        for(int i=0;i<MAXN;i++)
        {
            for(int j=0;j<MAXN;j++)
            {
                if(dis[i][j]>Add(dis[i][k],dis[k][j]))//里面别写成加号了!!
                {
                    dis[i][j]=Add(dis[i][k],dis[k][j]);
                }
            }
        }
    }
    return ;
}

void Child(int x)
{
    if(x==1) cout<<"child"<<endl;
    if(x==2) cout<<"grandchild"<<endl;
    if(x>2) 
    {
        x-=2;
        while(x--)
        {
            cout<<"great-";
        }
        cout<<"grandchild"<<endl;
    }
}

void Parent(int x)
{
    if(x==1) cout<<"parent"<<endl;
    if(x==2) cout<<"grandparent"<<endl;
    if(x>2) 
    {
        x-=2;
        while(x--)
        {
            cout<<"great-";
        }
        cout<<"grandparent"<<endl;
    }
}

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<MAXN;i++)
    {
        for(int j=0;j<MAXN;j++)
        {
            dis[i][j]=INF;
        }
        dis[i][i]=0;
    }
    for(int i=0;i<n;i++)
    {
        string str;
        cin>>str;
        dis[str[0]-'A'][str[1]-'A']=1;//有向图!
        dis[str[0]-'A'][str[2]-'A']=1;
    }
    Floyd(n);
    while(m--)
    {
        string ask;
        cin>>ask;
        if(dis[ask[0]-'A'][ask[1]-'A']==INF&&dis[ask[1]-'A'][ask[0]-'A']==INF) cout<<"-"<<endl;
        else if(dis[ask[0]-'A'][ask[1]-'A']!=INF&&dis[ask[1]-'A'][ask[0]-'A']==INF)
        {
            Child(dis[ask[0]-'A'][ask[1]-'A']);
        }
        else if(dis[ask[0]-'A'][ask[1]-'A']==INF&&dis[ask[1]-'A'][ask[0]-'A']!=INF)
        {
            Parent(dis[ask[1]-'A'][ask[0]-'A']);
        }
    }
    return 0;
}

发表于 2020-02-28 14:50:31 回复(0)
我有个疑问,如果有不同辈分的旁系亲属结婚(三代以外的旁系血亲结婚是合法的)这不是乱了辈分吗?不过我知道出题的人思路没我这么刁钻23333
言归正传,不考虑“贵圈真乱”的情况,这道题应该用二叉树,节点的两个指针分别指向两个双亲。查询AB的亲属关系时,先从A出发去找B(先序遍历),找到了就输出他俩差几辈,这种情况A是B的晚辈;没找到的话就从B出发去找A,找到了说明A是B的长辈,输出他们差几辈。两种情况都没找到说明不是直系亲属。
#include <stdio.h>
#include <map>
#define N 26
using namespace std;

struct Node{//二叉树节点
    int p1;//第一个双亲的下标,-1表示不存在
    int p2;//第二个双亲的下标,-1表示不存在
}tree[N];//顺序存储,下标就是它所代表的字符编号,比如0代表'A'

int preOrder(int from, int to, int depth)
{//从from出发先序遍历到找到to为止,并返回to相对于from的深度
    if(from==to) return depth;
    if(tree[from].p1!=-1)
    {
        int ret=preOrder(tree[from].p1, to, depth+1);
        if(ret!=-1) return ret;
    }
    if(tree[from].p2!=-1)
    {
        int ret=preOrder(tree[from].p2, to, depth+1);
        if(ret!=-1) return ret;
    }
    return -1;
}

int main()
{
    int n, m;
    while(scanf("%d %d", &n, &m)!=EOF)
    {
        for(int i=0; i<N; i++)
        {
            tree[i].p1=tree[i].p2=-1;
        }
        while(n--)//构建树
        {
            char str[4];
            scanf("%s", str);
            if(str[1]!='-') tree[str[0]-'A'].p1=str[1]-'A';
            if(str[2]!='-') tree[str[0]-'A'].p2=str[2]-'A';
        }
        while(m--)//查询
        {
            char str[3];
            scanf("%s", str);
            int from=str[0]-'A';
            int to=str[1]-'A';
            int ans1=preOrder(from, to, 0);
            if(ans1==1) printf("child\n");
            else if(ans1>=2)
            {
                for(int i=ans1; i>2; i--) printf("great-");
                printf("grandchild\n");
            }
            else//看来不是晚辈,那就是长辈了
            {
                int ans2=preOrder(to, from, 0);
                 if(ans2==1) printf("parent\n");
                else if(ans2>=2)
                {
                    for(int i=ans2; i>2; i--) printf("great-");
                    printf("grandparent\n");
                }
                else printf("-\n");//也不是长辈,那就不是直系亲属
            }
        }
    }
    return 0;//大功告成
}

编辑于 2018-03-11 16:43:31 回复(9)

问题信息

难度:
84条回答 8686浏览

热门推荐

通过挑战的用户

查看代码