• 1158 Telefraud Detection – PAT甲级真题


    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. #include
    2. #include
    3. using namespace std;
    4. int k, n, m, c, r, d, p[1001], sc[1001], rec[1001], mark[1001], record[1001][1001];
    5. vector<int> su;
    6. int Find(int a) {
    7. if (p[a] != a) return p[a] = Find(p[a]);
    8. return a;
    9. }
    10. void add(int a, int b) {
    11. int f1 = Find(a), f2 = Find(b);
    12. if (f1 < f2) p[f2] = f1;
    13. else p[f1] = f2;
    14. }
    15. int main() {
    16. for (int i = 1; i <= 1000; i++) p[i] = i;
    17. cin >> k >> n >> m;
    18. for (int i = 0; i < m; i++) {
    19. cin >> c >> r >> d;
    20. record[c][r] += d;
    21. }
    22. for (int i = 1; i <= n; i++) {
    23. for (int j = 1; j <= n; j++) {
    24. if (record[i][j] && record[i][j] <= 5) {
    25. sc[i]++;
    26. if (record[j][i]) rec[i]++;
    27. }
    28. }
    29. if (sc[i] > k && rec[i] * 5 <= sc[i]) su.push_back(i);
    30. }
    31. if (su.empty()) {
    32. cout << "None";
    33. return 0;
    34. }
    35. for (int i = 0; i < su.size(); i++) {
    36. for (int j = i + 1; j < su.size(); j++) {
    37. if (record[su[i]][su[j]] && record[su[j]][su[i]]) add(su[i], su[j]);
    38. }
    39. }
    40. for (int i = 0; i < su.size(); i++) {
    41. if (mark[su[i]]) continue;
    42. cout << su[i];
    43. for (int j = i + 1; j < su.size(); j++) {
    44. if (Find(su[i]) == Find(su[j])) {
    45. cout << ' ' << su[j];
    46. mark[su[j]] = 1;
    47. }
    48. }
    49. cout << '\n';
    50. }
    51. return 0;
    52. }

  • 相关阅读:
    [高等数学]同济版高等数学【第七版】上下册教材+习题全解PDF
    阿里云 linux tomcat 无法访问方法
    重新定义分析 - EventBridge 实时事件分析平台发布
    直播课堂系统,打造出超过线下培训场景200%的在线学习课堂
    win11疑难解答怎么进
    不必安装,快速设计数据库表结构
    基于二维切片图序列的三维立体建模MATLAB仿真
    QGIS003:【03捕捉工具栏】-点、线、面图层的捕捉操作
    在Windows10上编译grpc工程,得到protoc.exe和grpc_cpp_plugin.exe
    iOS App外包开发的内存泄露解决
  • 原文地址:https://blog.csdn.net/liuchuo/article/details/126222735