pat1034 Head of a Gang

题意:给出几组通话的人与通话时间,规定如果两人通话说明有联系,一个联系网络中的总通话时间超过阈值并且人数超过2人则把这个网络视为一个gang,其中通话时间最长的是head,输出每个gang的head和这个gang中的人数。

思路:并查集维护联通分量,用map映射一下集合和集合中的人,开数组记录一下每个人的通话时间即可。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>

using namespace std;

vector<string> v;
map<string, int> id;

int get_id(string x) {
    if (id.count(x)) return id[x];
    v.push_back(x);
    return id[x] = v.size()-1;
}

string get_s(int i) {
    return v[i];
}

const int MAX_N = 100000;
int par[MAX_N], n;

void init(int n) {
    for (int i = 0; i < n; i++) {
        par[i] = i;
    }
}

int find(int x) {
    if (par[x] == x) return x;
    return par[x] = find(par[x]);
}

void uni(int x, int y) {
    x = find(x); y = find(y);
    if (x == y) return ;
    par[x] = y;
}

int N, Y;
string a, b;
int t;
int cnt[MAX_N];
map<int, vector<int> > unio;
vector<string> ans;

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    cin >> N >> Y;
    init(N);
    for (int i = 0; i < N; i++) {
        cin >> a >> b >> t;
        int ida = get_id(a), idb = get_id(b);
        cnt[ida] += t; cnt[idb] += t;
        uni(ida, idb);
    }
    for (int i = 0; i < N; i++) {
        int x = find(i);
        unio[x].push_back(i);
    }
    for (auto it = unio.begin(); it != unio.end(); it++) {
        int tmp = 0;
        vector<int> &vv = it->second;
        int ma = 0, ind = -1;
        for (int i = 0; i < vv.size(); i++) {
            tmp += cnt[vv[i]];
            if (cnt[vv[i]] > ma) {
                ma = cnt[vv[i]];
                ind = vv[i];
            }
        }
        if (vv.size() > 2 && tmp > Y*2) ans.push_back(get_s(ind));
    }
    sort(ans.begin(), ans.end());
    cout << ans.size() << endl;
    for (int i = 0; i < ans.size(); i++) {
        cout << ans[i] << " " << unio[find(get_id(ans[i]))].size() << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/csx0987/article/details/82078672
今日推荐