• PAT甲级1139First Contact


    题目链接

    https://pintia.cn/problem-sets/994805342720868352/problems/994805344776077312

    题解

    题目要求

    • 背景

      男生A喜欢女孩B,A找男生C让女孩D跟B说,其中C是A的朋友,D是B和C的朋友。女生也是这样联系男生

    • 输入

      • N:人的数量,1到300
      • M:朋友关系的数量
      • M个朋友关系:用4位数字表示一个人,其中负数代表性别是女生
      • K:查询数量,不超过100
      • K次查询:每次查询是A和B的ID,假设A喜欢B
    • 输出

      • 输出有几对C和D可以帮助A联系B

      • 输出这几对C和D

        • 如果A和B是异性,则A和C应该是同性,B和D同性;如果A和B是同性,则这4人性别应该相同

          即A和C同性,B和D同性

        • 先按C的ID非降序输出,再按D的ID增序输出

    思路

    1. 使用邻接矩阵表示两个人是否是朋友,用邻接表存储一个人的同性朋友
    2. 给定A和B以后,枚举A的朋友C,枚举B的朋友D,如果C和D是朋友则保存C和D

    注意点

    • 输出时要以4位数字输出,用printf("%04d"),第二和第三个测试点都测试了这个
    • 如果用int接收一对朋友,-0000和0000对于int来说都是0,将无法得知这个人的性别
      • 在这里我对他们的id进行了处理:把女生映射到[0,9999],男生映射到[10000,19999]
      • 也可以使用其他的哈希方法
    • 正常回路为A-C-D-B,不可以形成A-B-D-B或A-C-A-B的回路,即AD不相等、BC不相等
    • 写循环代码时注意一些变量是否会随着循环运行而改变,比如数组大小、外层循环变量是否被内层循环改变

    代码

    // Problem: PAT Advanced 1139
    // URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805344776077312
    // Tags: Graph Hash
    
    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm>
    using namespace std;
    
    bool isFriend[20000][20000]; // 邻接矩阵
    vector<int> friends[20000]; // 邻接表,同性朋友
    
    struct Helper{
        int c, d;
    };
    
    int transform(string s){
        // 将负数映射到[0,9999],将正数映射到[10000,19999]
        if (s[0] == '-')
            return abs(stoi(s));
        else
            return 10000 + stoi(s);
    }
    
    int restore(int num){
        // 将transform得到的[0,19999]的数字映射到[0,9999],即原来的[-9999,9999]取绝对值得到[0,9999],以进行输出
        if (num > 9999)
            return num - 10000;
        else
            return num;
    }
    
    bool helperCmp(Helper& h1, Helper& h2){
        return h1.c == h2.c ? h1.d < h2.d : h1.c < h2.c;
    }
    
    int main()
    {
        int n, m, k, a, b, c ,d;
        string s, t;
        scanf("%d %d", &n, &m);
    
        for (int i = 0; i < m; i++){ // 将图存入邻接矩阵和邻接表
            cin >> s >> t;
            a = transform(s);
            b = transform(t);
            isFriend[a][b] = isFriend[b][a] = true;
            if ( (a<10000 && b<10000) || (a>9999 && b>9999) ){ // 同性则存储到邻接表
                friends[a].push_back(b);
                friends[b].push_back(a);
            }
        }
    
        scanf("%d", &k);
        while (k--){
            cin >> s >> t;
            a = transform(s);
            b = transform(t);
            vector<Helper> helpers;
            for (auto it1 = friends[a].begin(); it1 != friends[a].end(); it1++){
                c = *it1;
                if (c == b) // C和B不能是一个人
                    continue;
                for (auto it2 = friends[b].begin(); it2 != friends[b].end(); it2++){
                    d = *it2;
                    if (d == a) // D和A不能是一个人
                        continue;
                    if (isFriend[c][d])
                        helpers.push_back({restore(c), restore(d)});
                }
            }
            sort(helpers.begin(), helpers.end(), helperCmp);
            printf("%d
    ", helpers.size());
            for (auto it = helpers.begin(); it != helpers.end(); it++)
                printf("%04d %04d
    ", it->c, it->d);
        }
    
        return 0;
    }
    

    一份超时的代码

    // Problem: PAT Advanced 1139
    // URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805344776077312
    // Tags: Graph Hash Map
    
    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm>
    #include <unordered_map>
    using namespace std;
    
    struct Helper{
        string c, d;
    };
    
    bool helperCmp(Helper& h1, Helper& h2){
        return abs(stoi(h1.c)) == abs(stoi(h2.c)) ? abs(stoi(h1.d)) < abs(stoi(h2.d)) : abs(stoi(h1.c)) < abs(stoi(h2.c));
    }
    
    int main()
    {
        int n, m, k;
        string a, b, c, d;
        unordered_map<string, vector<string>> friends; // 会很耗时
        scanf("%d %d", &n, &m);
    
        for (int i = 0; i < m; i++){ // 存储朋友关系
            cin >> a >> b;
            if (a[0] != '-')
                a = '+' + a;
            if (b[0] != '-')
                b = '+' + b;
            friends[a].push_back(b);
            friends[b].push_back(a);
        }
        
        scanf("%d", &k);
        while (k--){
            cin >> a >> b; // a喜欢b
            if (a[0] != '-')
                a = '+' + a;
            if (b[0] != '-')
                b = '+' + b;
            vector<Helper> helpers;
            // 下边这个大的for循环也很耗时间
            for (auto it1 = friends[a].begin(); it1 != friends[a].end(); it1++){
                c = *it1; // a的朋友c
                if (b == c || a[0] != c[0]) // a和c不可以是同一个人,且应该是同性
                    continue;
                for (auto it2 = friends[c].begin(); it2 != friends[c].end(); it2++){
                    d = *it2; // c的朋友d
                    if (a == d || b[0] != d[0]) // a和d不可以是同一个人,且应该是同性
                        continue;
                    if (find(friends[d].begin(), friends[d].end(), b) != friends[d].end()){
                        helpers.push_back({c, d});
                    }
                }
            }
            sort(helpers.begin(), helpers.end(), helperCmp); // 按id升序存储,达到题目输出要求
            int num = helpers.size();
            printf("%d
    ", num);
            for (int i = 0; i < num; i++)
                printf("%04d %04d
    ", abs(stoi(helpers[i].c)), abs(stoi(helpers[i].d)));
        }
        return 0;
    }
    

    参考链接

    https://blog.csdn.net/liuchuo/article/details/79065004


    作者:@臭咸鱼

    转载请注明出处:https://www.cnblogs.com/chouxianyu/

    欢迎讨论和交流!


  • 相关阅读:
    System.web和System.WebServer
    Clone Detective java home
    2008年国外最佳Web设计/开发技巧、脚本及资源总结
    Multiview + UserControl 中UserControl如何判断首次执行
    .NET必看的几个网站
    深入剖析ASP.NET的编译原理之一:动态编译(Dynamical Compilation)(转)
    SQL Server 阻止了对组件 \'Ad Hoc Distributed Queries\' 的访问
    SQL SERVER 建表的限制
    dll文件
    com组件ConvertStringToBSTR(转)
  • 原文地址:https://www.cnblogs.com/chouxianyu/p/13597324.html
Copyright © 2020-2023  润新知