Telefraud(电信诈骗) remains a common and persistent problem in our society. In some cases, unsuspecting victims lose their entire life savings. To stop this crime, you are supposed to write a program to detect those suspects from a huge amount of phone call records.
A person must be detected as a suspect if he/she makes more than K short phone calls to different people everyday, but no more than 20% of these people would call back. And more, if two suspects are calling each other, we say they might belong to the same gang. A makes a short phone call to B means that the total duration of the calls from A to B is no more than 5 minutes.
Input Specification:
Each input file contains one test case. For each case, the first line gives 3 positive integers K (≤500, the threshold(阈值) of the amount of short phone calls), N (≤103, the number of different phone numbers), and M (≤105, the number of phone call records). Then M lines of one day’s records are given, each in the format:
caller receiver duration
where caller
and receiver
are numbered from 1 to N, and duration
is no more than 1440 minutes in a day.
Output Specification:
Print in each line all the detected suspects in a gang, in ascending order of their numbers. The gangs are printed in ascending order of their first members. The numbers in a line must be separated by exactly 1 space, and there must be no extra space at the beginning or the end of the line.
If no one is detected, output None
instead.
Sample Input 1:
5 15 31
1 4 2
1 5 2
1 5 4
1 7 5
1 8 3
1 9 1
1 6 5
1 15 2
1 15 5
3 2 2
3 5 15
3 13 1
3 12 1
3 14 1
3 10 2
3 11 5
5 2 1
5 3 10
5 1 1
5 7 2
5 6 1
5 13 4
5 15 1
11 10 5
12 14 1
6 1 1
6 9 2
6 10 5
6 11 2
6 12 1
6 13 1
Sample Output 1:
3 5
6
Note: In sample 1, although 1
had 9 records, but there were 7 distinct receivers, among which 5
and 15
both had conversations lasted more than 5 minutes in total. Hence 1
had made 5 short phone calls and didn’t exceed the threshold 5, and therefore is not a suspect.
Sample Input 2:
5 7 8
1 2 1
1 3 1
1 4 1
1 5 1
1 6 1
1 7 1
2 1 1
3 1 1
Sample Output 2:
None
题目大意:编写一个程序,从大量的通话记录中检测出电信诈骗嫌疑人。如果一个人每天给不同的人打超过K个短电话,但这些人中回电的比例不超过20%,那他可能是嫌疑人。而且,如果两个嫌疑人互相打电话,我们认为他们可能属于同一个团伙。A给B打短电话是指A到B的通话总时长不超过5分钟。给三个正整数:短电话数量的阈值K,不同电话号码的数量N,通话记录数量M。接下来M行给出一天的通话记录,格式为呼叫者caller、接收者receiver、时长duration。输出格式:在每一行输出一个团伙中所有检测到的嫌疑人,按数字升序排列。这些帮派按第一个成员的升序排列。一行中的数字必须使用1个空格分隔,并且行首或行尾不得有多余空格。
分析:p为并查集的父集,sc中存储短通话的人数,rec中存储短通话收到回电的人数,mark用来标记是否输出过,record记录两个人的通话总时长,su中保存嫌疑人的编号。我们先记录下来两人之间的通话总时间,以此来统计短通话以及回电的次数,进而判断出某个人是不是嫌疑人。如果没有嫌疑人,则输出None。因为要按照帮派输出,所以我们用并查集把互相通过电话的嫌疑人设置到同一个集合内,然后就可以输出答案了~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
#include <iostream> #include <vector> using namespace std; int k, n, m, c, r, d, p[1001], sc[1001], rec[1001], mark[1001], record[1001][1001]; vector<int> su; int Find(int a) { if (p[a] != a) return p[a] = Find(p[a]); return a; } void add(int a, int b) { int f1 = Find(a), f2 = Find(b); if (f1 < f2) p[f2] = f1; else p[f1] = f2; } int main() { for (int i = 1; i <= 1000; i++) p[i] = i; cin >> k >> n >> m; for (int i = 0; i < m; i++) { cin >> c >> r >> d; record[c][r] += d; } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (record[i][j] && record[i][j] <= 5) { sc[i]++; if (record[j][i]) rec[i]++; } } if (sc[i] > k && rec[i] * 5 <= sc[i]) su.push_back(i); } if (su.empty()) { cout << "None"; return 0; } for (int i = 0; i < su.size(); i++) { for (int j = i + 1; j < su.size(); j++) { if (record[su[i]][su[j]] && record[su[j]][su[i]]) add(su[i], su[j]); } } for (int i = 0; i < su.size(); i++) { if (mark[su[i]]) continue; cout << su[i]; for (int j = i + 1; j < su.size(); j++) { if (Find(su[i]) == Find(su[j])) { cout << ' ' << su[j]; mark[su[j]] = 1; } } cout << '\n'; } return 0; } |