呵呵。大家都知道五服以内不得通婚,即两个人最近的共同祖先如果在五代以内(即本人、父母、祖父母、曾祖父母、高祖父母)则不可通婚。本题就请你帮助一对有情人判断一下,他们究竟是否可以成婚?

输入格式:

输入第一行给出一个正整数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;
        }
    }
}

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐