PTA团体程序设计天梯赛 L2-016 愿天下有情人都是失散多年的兄妹(Java)(满分不超时)
·
呵呵。大家都知道五服以内不得通婚,即两个人最近的共同祖先如果在五代以内(即本人、父母、祖父母、曾祖父母、高祖父母)则不可通婚。本题就请你帮助一对有情人判断一下,他们究竟是否可以成婚?
输入格式:
输入第一行给出一个正整数N(2 ≤ N ≤104),随后N行,每行按以下格式给出一个人的信息:
本人ID 性别 父亲ID 母亲ID
其中ID是5位数字,每人不同;性别M代表男性、F代表女性。如果某人的父亲或母亲已经不可考,则相应的ID位置上标记为-1。
接下来给出一个正整数K,随后K行,每行给出一对有情人的ID,其间以空格分隔。
注意:题目保证两个人是同辈,每人只有一个性别,并且血缘关系网中没有乱伦或隔辈成婚的情况。
输出格式:
对每一对有情人,判断他们的关系是否可以通婚:如果两人是同性,输出Never Mind;如果是异性并且关系出了五服,输出Yes;如果异性关系未出五服,输出No。
输入样例:
24
00001 M 01111 -1
00002 F 02222 03333
00003 M 02222 03333
00004 F 04444 03333
00005 M 04444 05555
00006 F 04444 05555
00007 F 06666 07777
00008 M 06666 07777
00009 M 00001 00002
00010 M 00003 00006
00011 F 00005 00007
00012 F 00008 08888
00013 F 00009 00011
00014 M 00010 09999
00015 M 00010 09999
00016 M 10000 00012
00017 F -1 00012
00018 F 11000 00013
00019 F 11100 00018
00020 F 00015 11110
00021 M 11100 00020
00022 M 00016 -1
00023 M 10012 00017
00024 M 00022 10013
9
00021 00024
00019 00024
00011 00012
00022 00018
00001 00004
00013 00016
00017 00015
00019 00021
00010 00011
输出样例:
Never Mind
Yes
Never Mind
No
Yes
No
Yes
No
No
代码长度限制
16 KB
时间限制
200 ms
内存限制
64 MB
栈限制
8192 KB
import java.util.*;
import java.io.*;
/**
* 【L2-016 愿天下有情人都是失散多年的兄妹】
* [思路]:
* 1. 使用静态数组模拟家谱图,DFS回溯5代进行祖先比对。
* 2. 采用字节流快读 + 递归清理标记位
*/
public class Main {
static int[] father = new int[100005];
static int[] mother = new int[100005];
static char[] gender = new char[100005];
static boolean[] visited = new boolean[100005];
static boolean conflict = false;
public static void main(String[] args) throws Exception {
Reader fr = new Reader();
int n = fr.nextInt();
// 初始化双亲为 -1 (不可考)
Arrays.fill(father, -1);
Arrays.fill(mother, -1);
for (int i = 0; i < n; i++) {
int id = fr.nextInt();
gender[id] = fr.nextChar();
int f = fr.nextInt();
int m = fr.nextInt();
father[id] = f;
mother[id] = m;
// 补全父母性别:出现在父亲位置必为男,出现在母亲位置必为女
if (f != -1) gender[f] = 'M';
if (m != -1) gender[m] = 'F';
}
int k = fr.nextInt();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
while (k-- > 0) {
int id1 = fr.nextInt();
int id2 = fr.nextInt();
// 1. 同性判断
if (gender[id1] == gender[id2]) {
bw.write("Never Mind\n");
} else {
conflict = false;
// 2. DFS 标记 ID1 的五代祖先
searchAncestors(id1, 1, true);
// 3. DFS 探测 ID2 的五代祖先是否冲突
searchAncestors(id2, 1, false);
if (conflict) bw.write("No\n");
else bw.write("Yes\n");
// 4. 路径回溯清理,提速关键
clearVisited(id1, 1);
}
}
bw.flush();
bw.close();
}
/**
* @param id 当前访问 ID
* @param level 当前代数(本人为1)
* @param markMode true 为标记模式,false 为探测模式
*/
static void searchAncestors(int id, int level, boolean markMode) {
// 边界:ID无效、超过5代、或探测模式下已发现冲突
if (id == -1 || level > 5 || (conflict && !markMode)) return;
if (markMode) {
visited[id] = true;
} else {
if (visited[id]) {
conflict = true;
return;
}
}
// 递归回溯父系和母系
searchAncestors(father[id], level + 1, markMode);
searchAncestors(mother[id], level + 1, markMode);
}
/**
* 递归清理标记,避免 Arrays.fill 的高额开销
*/
static void clearVisited(int id, int level) {
if (id == -1 || level > 5) return;
visited[id] = false;
clearVisited(father[id], level + 1);
clearVisited(mother[id], level + 1);
}
/**
* 字节级极速读入类
*/
static class Reader {
private final InputStream in = System.in;
private final byte[] buf = new byte[1 << 16];
private int ptr = 0, len = 0;
private int read() throws Exception {
if (ptr == len) {
len = in.read(buf);
ptr = 0;
if (len <= 0) return -1;
}
return buf[ptr++];
}
public int nextInt() throws Exception {
int c = read();
while (c >= 0 && c <= 32) c = read();
if (c == -1) return -1;
//增加对负号 '-' 的识别,防止 -1 导致解析出错
boolean neg = false;
if (c == '-') {
neg = true;
c = read();
}
int res = 0;
while (c >= '0' && c <= '9') {
res = res * 10 + (c - '0');
c = read();
}
return neg ? -res : res;
}
public char nextChar() throws Exception {
int c = read();
while (c >= 0 && c <= 32) c = read();
return (char) c;
}
}
}

更多推荐




所有评论(0)