P2814 家谱
题目背景
现代的人对于本家族血统越来越感兴趣。
题目描述
给出充足的父子关系,请你编写程序找到某个人的最早的祖先。
输入格式
输入由多行组成,首先是一系列有关父子关系的描述,其中每一组父子关系中父亲只有一行,儿子可能有若干行,用 #name 的形式描写一组父子关系中的父亲的名字,用 +name 的形式描写一组父子关系中的儿子的名字;接下来用 ?name 的形式表示要求该人的最早的祖先;最后用单独的一个 $ 表示文件结束。
输出格式
按照输入文件的要求顺序,求出每一个要找祖先的人的祖先,格式为:本人的名字 + 一个空格 + 祖先的名字 + 回车。
输入输出样例
输入 #1 |
输出 #1 |
#George +Rodney #Arthur +Gareth +Walter #Gareth +Edward ?Edward ?Walter ?Rodney ?Arthur $ |
Edward Arthur Walter Arthur Rodney George Arthur Arthur |
说明/提示
规定每个人的名字都有且只有 6 个字符,而且首字母大写,且没有任意两个人的名字相同。最多可能有1e3 组父子关系,总人数最多可能达到 5e4人,家谱中的记载不超过 30 代。
题目分析
1 #为父亲,+为#的儿子。
2 也就是说,+对应的节点内要存储#的位置,此处分为两种情况:
- #是新的,在上面案例中没有。此时用一个新的节点放#就可以,之后的+元素直接存储这个新位置的信息。
- #是旧的,在上面案例中出现过。那么之后的+元素需要存储它第一次位置信息。
3 把?单独存到一个新的数组中,然后挨个去遍历它在集合中的位置,再通过集合去找它的祖宗输出即可。
可行代码
#include <iostream> #include <string.h> using namespace std; // const int MAX = 5e4 + 5; const int MAX = 20; struct { char name[10]; int parent; } family[MAX]; // 个人信息结构体,集合用这个数组表示 void init(int len) { for (int i = 0; i < len; i++) family[i].parent = i; return; } int find(int aim) { if (family[aim].parent != aim) aim = find(family[aim].parent); return aim; } void merge(int a, int b) { a = find(a), b = find(b); if (a != b) family[b].parent = a; return; } int search(char *str, int len) { char *p = str; p++; int i; for (i = 0; i < len; i++) { char *q = family[i + 1].name; q++;// 输入时输入了前缀+#?,这里排除 if (strcmp(p, q) == 0) break; } if (i == len) return -1; return i + 1; } int main() { int cnt = 1, count = 0; int FindParent[MAX]; init(MAX); while (1) { // 输入数组,并建立集合 int TempParent; cin >> family[cnt].name; if (*(family[cnt].name) == '$') break; else if (*(family[cnt].name) == '#') { int loc = search(family[cnt].name, cnt); // 判断之前是否出现过 if (loc != -1 && loc != cnt) { TempParent = loc; continue; } family[cnt].parent = cnt; TempParent = cnt;// 后面的+元素,都是它的孩子 } else if (*(family[cnt].name) == '+') { family[cnt].parent = TempParent; int loc = search(family[cnt].name, cnt);// 出现过不能计入总数 if (loc != -1 && loc != cnt) { family[loc].parent = TempParent; --cnt; } } else if (*(family[cnt].name) == '?') { int loc = search(family[cnt].name, cnt);// ?元素,不计入集合 FindParent[count++] = loc; cnt--; } cnt++; } // while end for (int i = 0; i < count; i++) { int loc = search(family[FindParent[i]].name, cnt);// 找到元素再集合中的位置 int ancestor = find(loc); char *p = family[FindParent[i]].name; char *q = family[ancestor].name;// 找父亲 p++, q++;// 排除前缀+# cout << p << ' ' << q << endl; } return 0; }
END 感谢rueader's阅读,洛谷题目链接:P2814 家谱 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
原文地址:https://www.cnblogs.com/kirk-notes/p/15001382.html
- 《C#并发编程经典实例》笔记
- 用mysqlslap进行mysql压力测试
- 域名Matrix.io以20万元结拍,被搭建区域链相关网站
- 结合ABP源码实现邮件发送功能
- Discuz!关于出现“对不起,您安装的不是正版应用”的解决办法
- 利用C#迭代器的一个杨辉三角示例
- 计算机组成原理之机器
- Elasticsearch 健康状态处理
- 开始菜单中没有运行时怎么办
- Elasticsearch 的一些关键概念
- Elasticsearch 相关 api 操作
- 【前端开发系列】—— 文字阴影与样式
- Elasticsearch 在 windows 和 ubuntu 下详细安装过程
- 【前端开发系列】—— 利用选择器添加内容
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- JWT对SpringCloud进行认证和鉴权
- @SpringBootConfiguration注解
- spring注解之@Import注解的三种使用方式
- 为什么我要写spring.factories文件?
- Tiny85哒哒哒哒
- Tiny85哒哒哒
- Julia机器核心编程.多重分配
- 常用注解使用总结系列: @Order 注解
- Fake伪造数据集
- @EnableDiscoveryClient 注解如何实现服务注册与发现
- idea连接docker实现一键部署
- redis的过期策略和内存淘汰机制
- Redis主从复制原理总结
- redis cluster 的核心原理分析:gossip 通信、jedis smart 定位、主备切换
- SpringBoot自动装配原理解析