1158 Telefraud Detection(最后一个测试点通过)+ BFS + 并查集模板复习

又是稀碎的一天,真的是写代码10分钟,找bug俩小时(最后一个测试点没过的bug找到了:判断不超过5 minutes,我算的不是总时间total)。

PAT题目链接:https://pintia.cn/problem-sets/994805342720868352/exam/problems/1478635060278108160

BFS的题解代码:

#include<iostream>
#include<vector>
#include<queue>
#include<set>
#include<algorithm>
using namespace std;

struct node {
    set<int> call_to, called_by, all_call_to, all_called_by;
    bool suspect;
} g[1005];

int duration[1005][1005]; // 后来找bug加上去了
int k, n, m;
vector<vector<int>> gang; 
vector<int> s;

set<int> path;
int vis[1005];

void bfs(int cur) {
    queue<int> q;
    path.insert(cur);
    q.push(cur);
    vis[cur] = 1;
    while (q.size()) {
        int ind = q.front(); q.pop();
        for (auto x : g[ind].all_call_to) {
            if (!vis[x] && g[x].suspect && g[ind].all_called_by.find(x) != g[ind].all_called_by.end()) {
                path.insert(x);
                q.push(x);
                vis[x] = 1;
            }
        }
    }
}

bool cmp(vector<int> &a, vector<int> &b) {
    return a[0] < b[0];
}
int main() {
    cin >> k >> n >> m;
    for (int i = 0; i < m; i++) {
        int a, b, d;
        scanf("%d%d%d", &a, &b, &d);
        g[a].all_call_to.insert(b);
        g[b].all_called_by.insert(a);
        duration[a][b] += d;
    }
    for (int i = 1; i <= n; i++) {
        for (auto x : g[i].all_call_to) {
            if (duration[i][x] <= 5) {
                g[i].call_to.insert(x);
            }
            if (g[x].call_to.find(i) != g[x].call_to.end()) {
                g[x].called_by.insert(i);
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        if (g[i].call_to.size()) {
            g[i].suspect = (g[i].call_to.size() > k) && g[i].called_by.size() <= (g[i].call_to.size() / 5);
            if (g[i].suspect) {
                s.push_back(i);
            }
        } 
    }
    for (auto x : s) {
        if (!vis[x]) {
            path.clear();
            bfs(x);
            vector<int> v;
            for (auto x : path) v.push_back(x);
            gang.push_back(v);
        }
    }
    if (gang.size()) {
        sort(gang.begin(), gang.end(), cmp);
        for (int i = 0; i < gang.size(); i++) {
            for (int j = 0; j < gang[i].size(); j++) {
                j && cout << " ";
                cout << gang[i][j];
            }
            cout << "\n";
        }
    } else {
        cout << "None" << endl;
    }

    return 0;
}

网上清一色都是并查集的做法。那就顺便巩固一下并查集吧。

并查集通用模板:

struct UnionSet {
    int *fa, n;
    UnionSet(int n) : n(n) {
        fa = new int[n + 1];
        for (int i = 0; i <= n; i++) {
            fa[i] = i;
        }
    }
    int get(int x) {
        return fa[x] = (fa[x] == x ? x : get(fa[x]));
    }
    void merge(int a, int b) {
        fa[get(a)] = get(b);
    }
};
posted @ 2023-05-02 16:40  江韵阁  阅读(79)  评论(0)    收藏  举报