时间限制
400 ms
内存限制
64 MB
题目描述:
2018年世界杯,冰岛队因1:1平了强大的阿根廷队而一战成名。好事者发现冰岛人的名字后面似乎都有个“松”(son),于是有网友科普如下:
冰岛人沿用的是维京人古老的父系姓制,孩子的姓等于父亲的名加后缀,如果是儿子就加 sson,女儿则加 sdottir。因为冰岛人口较少,为避免近亲繁衍,本地人交往前先用个 App 查一下两人祖宗若干代有无联系。本题就请你实现这个 App 的功能。
输入格式:
输入首先在第一行给出一个正整数
N
(
1
<
N
≤
1
0
5
)
N(1 < N \le 10^{5} )
N(1<N≤105),为当地人口数。随后 N 行,每行给出一个人名,格式为:名 姓(带性别后缀)
,两个字符串均由不超过 20 个小写的英文字母组成。维京人后裔是可以通过姓的后缀判断其性别的,其他人则是在姓的后面加 m
表示男性、f
表示女性。题目保证给出的每个维京家族的起源人都是男性。
随后一行给出正整数 M,为查询数量。随后 M 行,每行给出一对人名,格式为:名1 姓1 名2 姓2
。注意:这里的姓
是不带后缀的。四个字符串均由不超过 20 个小写的英文字母组成。
题目保证不存在两个人是同名的。
输出格式:
对每一个查询,根据结果在一行内显示以下信息:
- 若两人为异性,且五代以内无公共祖先,则输出
Yes
; - 若两人为异性,但五代以内(不包括第五代)有公共祖先,则输出
No
; - 若两人为同性,则输出
Whatever
; - 若有一人不在名单内,则输出
NA
。
所谓“五代以内无公共祖先”是指两人的公共祖先(如果存在的话)必须比任何一方的曾祖父辈分高。
输入样例:
15
chris smithm
adam smithm
bob adamsson
jack chrissson
bill chrissson
mike jacksson
steve billsson
tim mikesson
april mikesdottir
eric stevesson
tracy timsdottir
james ericsson
patrick jacksson
robin patricksson
will robinsson
6
tracy tim james eric
will robin tracy tim
april mike steve bill
bob adam eric steve
tracy tim tracy tim
x man april mikes
输出样例:
Yes
No
No
Whatever
Whatever
NA
给定n个人的姓名,求m组人名的关系。
题目保证不存在两个人是同名的。
孩子的姓等于父亲的名加后缀。
emmmmmmm
在输入n个人的姓名时,通过
姓的性别后缀
来判断是否为维京人后裔
- 后缀为
sson
与sdottir
,则为维京人后裔
- 后缀为
m
与f
,则为其他人
–sson
与m
,表示男
–sdottir
与f
,表示女然后用名来存储,每个人的性别与姓
然后再判断m组人名的时候
先判断两个人是否都出现在名单中
- 未出现, 则输出
NA
- 出现,则判断两个人性别是否相同
- 相同, 则输出
Whatever
- 最后判断两个人是否五代内有公共祖先
- 出现,则输出
No
- 未出现, 则输出
Yes
如何判断两个人是否五代以内呢?
- 因为
孩子的姓等于父亲的名
- 所以可以通过判断当前这个人的姓往上找祖先
注: 本题我java过不去,最后一个数据怎么都是TLE
import java.io.*;
import java.util.*;
public class Main
{
static TreeMap<String, edge> tr = new TreeMap<String, edge>();
static String check(String a, String b)
{
int cnt1 = 0; // a的第几代祖先了
while (!a.equals("")) // 如果a还有祖先
{
int cnt2 = 0; // b的第几代祖先了
String c = b; // b的第0代祖先为自己
while (!c.equals("")) // 如果b还有祖先
{
// 如果a的祖先与b的祖先相同,并且在5代以内
if (a.equals(c) && (cnt1 < 4 || cnt2 < 4)) return "No";
// 如果当前判断的a祖先与b祖先都超过了5代
if (cnt1 >= 4 && cnt2 >= 4) return "Yes";
c = tr.get(c).fname; // 替换b的祖先
cnt2++; // b的祖先代数增加
}
a = tr.get(a).fname; // 替换a的祖先
cnt1++; // a的祖先代数增加
}
return "Yes";
}
public static void main(String[] args)
{
int n = sc.nextInt();
while (n-- > 0)
{
String sname = sc.next(); // 名
String fname = sc.next(); // 姓
// 姓的长度
int len = fname.length();
// 姓中的带性别后缀
char op = fname.charAt(len - 1);
// 如果是维京人后裔的男
if (op == 'n') tr.put(sname, new edge(1, fname.substring(0, len - 4)));
// 如果是维京人后裔的女
else if (op == 'r') tr.put(sname, new edge(0, fname.substring(0, len - 7)));
// 如果是其他人的男
else if (op == 'm') tr.put(sname, new edge(1, ""));
// 如果是其他人的女
else if (op == 'f') tr.put(sname, new edge(0, ""));
}
int m = sc.nextInt();
while (m-- > 0)
{
String sname1 = sc.next();
String fname1 = sc.next();
String sname2 = sc.next();
String fname2 = sc.next();
// 判断两个人是否有一个人不在名单内
if (!tr.containsKey(sname1) || !tr.containsKey(sname2)) out.println("NA");
// 判断两个人是否同性
else if (tr.get(sname1).sex == tr.get(sname2).sex) out.println("Whatever");
else out.println(check(sname1, sname2));
}
out.flush();
out.close();
}
static class edge
{
int sex; // 性别
String fname; // 姓(也就是父亲的名)
public edge(int sex, String fname)
{
this.sex = sex;
this.fname = fname;
}
}
static Scanner sc = new Scanner(System.in);
static PrintWriter out = new PrintWriter(System.out);
}
c++
#include <iostream>
#include <unordered_map>
#define PIS pair<int, string>
using namespace std;
const int N = 1e5 + 10;
unordered_map<string, PIS> mp;
string check(string a, string b)
{
int cnt1 = 0;
while(a != "")
{
int cnt2 = 0;
string c = b;
while(c != "")
{
if(a == c && (cnt1 < 4 || cnt2 < 4)) return "No";
if(cnt1 >= 4 && cnt2 >= 4) return "Yes";
c = mp[c].second;
cnt2 ++;
}
a = mp[a].second;
cnt1 ++;
}
return "Yes";
}
int main()
{
int n; cin >> n;
while(n -- > 0)
{
string a, b; cin >> a >> b;
if(b.back() == 'n') mp[a] = {1, b.substr(0, b.size() - 4)};
else if(b.back() == 'r') mp[a] = {0, b.substr(0, b.size() - 7)};
else if(b.back() == 'm') mp[a] = {1, ""};
else if(b.back() == 'f') mp[a] = {0, ""};
}
int m; cin >> m;
while(m -- > 0)
{
string a, b, c, d; cin >> a >> b >> c >> d;
if(!mp.count(a) || !mp.count(c)) cout << "NA\n";
else if(mp[a].first == mp[c].first) cout << "Whatever\n";
else cout << check(a, c) << "\n";
}
return 0;
}
如果有说错的 或者 不懂的 尽管提 嘻嘻
一起进步!!!