亲戚详解YBT1346

题目链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1346

【例4-7】亲戚(relation)

时间限制: 1000 ms         内存限制: 65536 KB
提交数: 470     通过数: 203 
【题目描述】
或许你并不知道,你的某个朋友是你的亲戚。他可能是你的曾祖父的外公的女婿的外甥女的表姐的孙子。如果能得到完整的家谱,判断两个人是否是亲戚应该是可行的,但如果两个人的最近公共祖先与他们相隔好几代,使得家谱十分庞大,那么检验亲戚关系实非人力所能及。在这种情况下,最好的帮手就是计算机。为了将问题简化,你将得到一些亲戚关系的信息,如Marry和Tom是亲戚,Tom和Ben是亲戚,等等。从这些信息中,你可以推出Marry和Ben是亲戚。请写一个程序,对于我们的关于亲戚关系的提问,以最快的速度给出答案。

【输入】
输入由两部分组成。

第一部分以N,M开始。N为问题涉及的人的个数(1N20000)。这些人的编号为1,2,3,…, N。下面有M行(1≤M≤1000000),每行有两个数ai,biai,bi,表示已知aiai和bibi是亲戚。

第二部分以Q开始。以下Q行有Q个询问(1≤ Q ≤1000000),每行为ci,dici,di,表示询问cici和didi是否为亲戚。

【输出】
对于每个询问ci,dici,di,输出一行:若cici和didi为亲戚,则输出“Yes”,否则输出“No”。

【输入样例】
10 7
2 4
5 7
1 3
8 9
1 2
5 6
2 3
3
3 4
7 10
8 9
【输出样例】
Yes
No
Yes
【来源】

No

分析:本题要求我们判断亲戚之间的关系,即构造一颗关系树,查找子节点与父节点的关系,用并查集再好不过了。

#include <iostream>
#include <cstdio>
using namespace std;
int fa[20002];//存储父节点
int ffind(int x) { //查找父节点函数,用ffind避免与保留字find冲突
    if(fa[x]!=x)/*自身非祖先*/fa[x]=ffind(fa[x]);//寻找上一任祖先,递归实现,路径压缩
    return fa[x];
}
void uunion(int x,int y) { //连接两个父节点,用uunion避免与union冲突
    fa[y]=x;//连接两个节点,暂不使用路径压缩
}
int main() {
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
        fa[i]=i;//初始化,每个人都是自己的祖先
    int x,y;
    while(m--) {
        scanf("%d%d",&x,&y);//需要连接的两人
        x=ffind(x);
        y=ffind(y);
        if(x!=y)/*如果两人不是一家*/uunion(x,y);//将两人并在一起
    }
    int q;
    scanf("%d",&q);
    while(q--) {
        scanf("%d%d",&x,&y);//需要询问关系的两人
        if(ffind(x)==ffind(y))/*如果是一家,即祖先相同 */                                printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

运行结果
这里写图片描述
GET结果
这里写图片描述
Thank you!
Bye-bye!

<think>好的,我需要帮助用户实现他们族谱管理应用的进阶功能。用户之前已经得到了一个关于使用Vue.js开发族谱应用的思路,包括核心功能、技术选型和代码示例。现在他们希望根据之前提到的进阶功能建议,具体实现其中的某些功能。用户提到“柑橘你的进阶功能建议帮我 写出代码”,可能是一个笔误,应该是“根据你的进阶功能建议帮我写出代码”。因此,我需要从之前提到的五个进阶功能中选择一个或多个,给出具体的代码示例。 首先,回顾之前的进阶功能建议: 1. 时间轴功能:展示家族历史事件 2. 血缘计算:自动计算亲属关系称谓 3. 隐私保护:敏感信息加密处理 4. 分享功能:生成可分享的家族图谱链接 5. 智能推荐:通过姓名分析地域来源 用户没有具体指明需要哪个功能,因此我需要选择一个较为常见且容易实现的作为示例。时间轴功能和血缘计算可能较为复杂,而分享功能或隐私保护可能更适合快速演示。不过,考虑到用户可能对血缘关系称谓计算感兴趣,这个功能在族谱应用中比较实用,所以选择“血缘计算:自动计算亲属关系称谓”作为示例。 接下来,我需要设计如何根据成员之间的关系计算称谓。血缘称谓的计算需要考虑多种关系,如父母、子女、兄弟姐妹、祖父母、叔伯、堂兄弟等。这需要遍历族谱树,确定成员之间的辈分和关系路径,然后根据预设的规则映射到对应的称谓。 在实现时,可以定义一个函数,传入当前用户ID和目标成员ID,然后查找两者之间的关系路径,最后返回对应的称谓。这涉及到族谱树的遍历和关系路径的分析,可能较为复杂。为了简化,可以预先定义一些常见的亲属关系规则,例如父子、母子、兄弟姐妹、祖孙等,并根据这些规则返回称谓。 另外,需要考虑中英文称谓的差异,中文的亲属称谓比较复杂,不同地区可能有不同的叫法。这里以常见的普通话称谓为例,进行简化处理。 在代码结构方面,可以创建一个工具函数或Composable函数,用于处理血缘计算。使用Pinia状态管理来获取族谱数据,然后根据成员之间的关系计算称谓。 现在需要编写示例代码,展示如何实现这一功能。例如,给定两个成员ID,如何判断他们之间的关系,并返回正确的中文称谓。可能需要处理的情况包括:父母、子女、兄弟姐妹、祖父母、叔伯、姑姑、堂兄弟姐妹、表兄弟姐妹等。 可能的步骤: 1. 获取两个成员的详细信息,包括他们的父母、子女、配偶等。 2. 确定两者之间的辈分差异(如相差一代、两代等)。 3. 根据共同的祖先或亲属关系路径,判断具体的亲属类型。 4. 根据性别、年龄等因素,返回正确的称谓。 由于这是一个复杂的问题,可能需要分步骤处理,首先处理直系亲属(父母、子女),然后是旁系亲属(兄弟姐妹、叔伯等),最后处理更复杂的远亲关系。 在代码示例中,可能需要使用递归或广度优先搜索来查找共同祖先,或者确定两个成员之间的最短路径。这可能超出简单示例的范围,因此可以简化处理,仅处理直系和一级旁系亲属,例如父母、子女、兄弟姐妹、祖父母、孙子女、叔伯、姑姑、侄子侄女等。 例如,判断成员A是否是成员B的父亲,母亲,儿子,女儿,兄弟,姐妹,祖父,祖母,叔叔,阿姨等。根据这些关系返回对应的称谓。 在代码实现中,可以编写一个函数getRelationship(currentMemberId, targetMemberId),返回对应的称谓。 需要考虑的情况: - 如果目标成员是当前成员的父辈: - 父亲、母亲 - 祖父、祖母 - 曾祖父、曾祖母等 - 如果目标成员是当前成员的子辈: - 儿子、女儿 - 孙子、孙女 - 如果目标成员是当前成员的同辈: - 兄弟、姐妹 - 堂兄弟、堂姐妹 - 表兄弟、表姐妹 - 如果目标成员是当前成员的叔伯辈: - 叔叔、伯伯、姑姑 - 如果目标成员是当前成员的侄子辈: - 侄子、侄女 需要根据双方的父母、子女关系,以及是否有共同的祖先来判断。 例如,判断两人是否有共同的父母,即为兄弟姐妹;如果一方是另一方的父辈,则根据性别判断父亲或母亲;如果对方的父辈是当前成员的兄弟,则对方是当前成员的侄子侄女等。 这需要大量的条件判断,可能需要编写多个辅助函数来检查各种亲属关系。 在示例代码中,可以简化处理,仅处理直系亲属和兄弟姐妹,以及叔伯侄子关系,作为示例。 此外,需要注意数据的获取,假设使用Pinia存储族谱数据,可以通过store获取成员信息。 现在,需要将这些思路转化为具体的代码示例,展示如何实现血缘称谓的计算,并在Vue组件中使用该功能。 可能还需要考虑成员性别,因为称谓可能因性别而异(如叔叔 vs 姑姑)。 总结,步骤: 1. 创建血缘计算工具函数,接收两个成员ID。 2. 获取两个成员的详细信息。 3. 判断两者的关系类型(父子、兄弟等)。 4. 根据关系类型和性别返回对应的称谓。 现在,编写示例代码,展示这一过程。</think>--- 以下针对 **血缘计算** 功能,实现自动计算亲属关系称谓的核心代码示例: --- ### 1. 血缘关系计算工具类 ```javascript // utils/relationshipCalculator.js import { useFamilyStore } from '@/stores/familyStore' // 称谓映射表(简版) const RELATIONSHIPS = { father: { male: '父亲', female: null }, mother: { male: null, female: '母亲' }, son: { male: '儿子', female: '女儿' }, sibling: { male: '兄弟', female: '姐妹' }, uncle: { male: '叔叔', female: '姑姑' }, nephew: { male: '侄子', female: '侄女' }, grandfather: { male: '祖父', female: '祖母' } } export function getRelationship(currentId, targetId) { const store = useFamilyStore() const current = store.members.find(m => m.id === currentId) const target = store.members.find(m => m.id === targetId) // 直系亲属判断 if (current.parents.includes(targetId)) { return target.gender === 'male' ? RELATIONSHIPS.father.male : RELATIONSHIPS.mother.female } if (target.parents.includes(currentId)) { return current.gender === 'male' ? RELATIONSHIPS.son.male : RELATIONSHIPS.son.female } // 兄弟姊妹判断 const hasCommonParent = current.parents.some(p => target.parents.includes(p)) if (hasCommonParent) { return target.gender === 'male' ? RELATIONSHIPS.sibling.male : RELATIONSHIPS.sibling.female } // 叔侄关系判断 const uncles = current.parents .flatMap(pId => store.members.find(m => m.id === pId)?.parents || []) .flatMap(gpId => store.members.find(m => m.id === gpId)?.children || []) .filter(cId => !current.parents.includes(cId)) if (uncles.includes(targetId)) { return target.gender === 'male' ? RELATIONSHIPS.uncle.male : RELATIONSHIPS.uncle.female } // 祖孙关系判断 const grandparents = current.parents .flatMap(pId => store.members.find(m => m.id === pId)?.parents || []) if (grandparents.includes(targetId)) { return target.gender === 'male' ? RELATIONSHIPS.grandfather.male : RELATIONSHIPS.grandfather.female } return '亲属' } ``` --- ### 2. Vue组件使用示例 ```vue <!-- components/RelationshipDisplay.vue --> <template> <div class="relationship-card"> <h3>{{ currentMember.name }} 称呼 {{ targetMember.name }} 为:</h3> <div class="result"> {{ relationshipResult }} </div> </div> </template> <script setup> import { computed } from 'vue' import { getRelationship } from '@/utils/relationshipCalculator' const props = defineProps({ currentMemberId: Number, targetMemberId: Number }) const relationshipResult = computed(() => { return getRelationship(props.currentMemberId, props.targetMemberId) }) </script> ``` --- ### 3. 功能扩展建议 1. **增加辈分计算**: ```javascript // 在工具类中添加 function getGenerationDifference(current, target) { const findDepth = (id, depth = 0) => { const member = store.members.find(m => m.id === id) return member.parents.length > 0 ? Math.max(...member.parents.map(p => findDepth(p, depth + 1))) : depth } return findDepth(current.id) - findDepth(target.id) } ``` 2. **复杂关系处理**: ```javascript // 处理堂表亲关系 if (Math.abs(getGenerationDifference(current, target)) === 0) { const currentGrandParents = current.parents.flatMap(p => store.members.find(m => m.id === p).parents) const targetGrandParents = target.parents.flatMap(p => store.members.find(m => m.id === p).parents) if (currentGrandParents.some(gp => targetGrandParents.includes(gp))) { return current.gender === 'male' ? '堂兄' : '堂妹' } } ``` --- ### 4. 使用示例 ```vue <!-- 在成员详情页使用 --> <template> <RelationshipDisplay :current-member-id="selectedMember.id" :target-member-id="hoveredMember.id" /> </template> ``` --- ### 实现原理说明 1. **数据依赖**:通过 Pinia 存储的成员数据进行关系计算 2. **核心逻辑**: - 优先判断直系亲属(父子、祖孙) - 其次判断旁系亲属(兄弟、叔侄) - 最后处理复杂关系(堂表亲) 3. **性别区分**:根据成员性别返回不同称谓 4. **扩展性**:可通过添加新的判断条件支持更多关系类型 需要更详细的某类关系(如舅甥关系)实现代码,可以告诉我具体需求!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值