题目太长就不粘了。
一. 题意理解
有 2N 行输入,每行包括一个 ID 和一个 IP,一个人可以有两个ID,但他的 IP 是固定且唯一的。第一次出现的ID是主ID, 第二次出现的 ID是主 ID 的 MaJia。要求输出MJ关系。
给出输入和输出:
Sample Input
8
inkfish 192.168.29.24 (1)
zhi 192.168.29.235 (2)
magicpig 192.168.50.170 (3)
pegasus 192.168.29.235 (2)
iamcs 202.116.77.131 (4)
finalBob 192.168.29.24 (1)
tomek 202.116.77.131 (4)
magicduck 192.168.50.170 (3)
4
mmmmmm 172.16.72.126 (1)
kkkkkk 192.168.49.161 (2)
llllll 192.168.49.161 (2)
nnnnnn 172.16.72.126 (1)
0
Sample Output
tomek is the MaJia of iamcs
finalBob is the MaJia of inkfish
magicduck is the MaJia of magicpig
pegasus is the MaJia of zhi
llllll is the MaJia of kkkkkk
nnnnnn is the MaJia of mmmmmm
以第一组输入为例,inkfish是第一次出现的ID,IP是192.168.29.24。这个IP还出现了一次,此时ID为
finalBob,那么就说finalBob是inkfish的MaJia。题目对输出还有一个要求,即主ID以字典序排列。比如说第一组输出,iamcs<inkfish<magicpig<zhi。
二. 解题思路
我们发现ID和IP具有很强的对应关系,而且都是string,所以可以考虑使用map。关于map的使用,这篇博客介绍得很详细。
利用 map 的对应的特点,map 的 first 和 second 都是string。我认为这题麻烦的地方在于需要按照字典序输出,因此我采用了两个map,分别为 m1 和 m2。m1用来存储ID和IP的关系,m2用来存储主ID和MJID的关系。
我们可以在输入时以 IP 作为 m1 的first,以主 ID 作为 m1 的 second。如果一个 IP 已经出现过(用库函数 count 判断),说明这个 ID 是 MJ,那么将这个IP的主 ID 作为 m2 的first,将第 MJ 作为 m2 的 second(建立这种对应关系,是为了对主ID 排序完毕之后便于输出)。
三. 代码实现
#include<iostream>
#include<map>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
int n;
while (cin >> n && n != 0) {
map<string, string> m1;
map<string, string> m2;
vector<string> tmp;
string str1, str2;
for (int i = 0; i < n; i++) {
cin >> str1 >> str2;
if (m1.count(str2)) { //输入的IP已经出现过
m2[m1[str2]] = str1; //m1[str2]是第一次出现的ID
tmp.push_back(m1[str2]); //主ID存入tmp,便于排序
}
else m1[str2] = str1; //输入的IP没出现过,存入m1中
}
sort(tmp.begin(), tmp.end()); //将主ID排序
for (int i = 0; i < tmp.size(); i++) {
cout << m2[tmp[i]] << " is the MaJia of " << tmp[i] << endl;
}
cout << endl;
}
return 0;
}
四. 总结与心得
本题的难点在于按照字典序输出。输入的每一行中 ID 和 IP 的对应关系很适合使用 map,理解了 map 的功能不难想到解决办法。时间复杂度分析:使用了 count 函数,时间复杂度为O(n*log(n)*L),其中 L 为字符串的最大长度。