One way that the police finds the head of a gang is to check people’s phone calls. If there is a phone call between A and B, we say that A and B is related. The weight of a relation is defined to be the total time length of all the phone calls made between the two persons. A “Gang” is a cluster of more than 2 persons who are related to each other with total relation weight being greater than a given threthold K. In each gang, the one with maximum total weight is the head. Now given a list of phone calls, you are supposed to find the gangs and the heads.
输入描述:
For each case, the first line contains two positive numbers N and K (both less than or equal to 1000), the number of phone calls and the weight threthold, respectively. Then N lines follow, each in the following format:
Name1 Name2 Time
where Name1 and Name2 are the names of people at the two ends of the call, and Time is the length of the call. A name is a string of three capital letters chosen from A-Z. A time length is a positive integer which is no more than 1000 minutes.
输出描述:
For each test case, first print in a line the total number of gangs. Then for each gang, print in a line the name of the head and the total number of the members. It is guaranteed that the head is unique for each gang. The output must be sorted according to the alphabetical order of the names of the heads.
示例1
输入
8 59
AAA BBB 10
BBB AAA 20
AAA CCC 40
DDD EEE 5
EEE DDD 70
FFF GGG 30
GGG HHH 20
HHH FFF 10
8 70
AAA BBB 10
BBB AAA 20
AAA CCC 40
DDD EEE 5
EEE DDD 70
FFF GGG 30
GGG HHH 20
HHH FFF 10
输出
2
AAA 3
GGG 3
0
题目大意:
确定一个团队队长的方案是看队员彼此之间的通话时间。如果一个团队中,某个队员和其他队员的通话时间是最长的,那么他就是队长。有一些案例,输入为一些人之间的相互通话时间。找出每个案例中的团队个数,团队的限制应该是2个人以上(不包含2个人)并且队员之间总的通话时间大于限制时间K,找出团队的队长和该团队的成员个数。
解题思路:
1、由于每个人的ID是通过字符串给出的,因此需要离散化。注意输出时要输出队长所对应的字符串,因此可以使用两个map来进行字符串与编号之间的来回映射;
2、使用并查集来寻找各个团队;
3、按照要求对所有队长的名字进行排序后输出。
AC代码:
#include<iostream>
#include<stdio.h>
#include<map>
#include<algorithm>
#include<string>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
#define maxn 2010
int weight[maxn];//每个人员的总通话时间
int tree[maxn];
map<string, int> Map;//使用两个map来进行姓名与编号之间的来回映射
map<int, string> idx;
int cnt;//总的人员数量
void init() {
for (int i = 0; i < maxn; i++) {
weight[i] = 0;
tree[i] = -1;
}
Map.clear();
idx.clear();
cnt = 0;//下一个可用的编号
}
int findroot(int a) {
if (tree[a] == -1)return a;
int tmp = findroot(tree[a]);
tree[a] = tmp;
return tmp;
}
void unit(int a, int b) {//合并根
int fa = findroot(a);
int fb = findroot(b);
if (fa != fb) tree[fa] = fb;
}
struct gang {//团伙首领
string name;
int size;//团伙大小
bool operator < (const gang &a) const {//按照首领姓名的字典序排列
return name < a.name;
}
};
int main() {
int n, k;
while (cin>>n>>k) {
init();//初始化
string a, b; int w;
while (n--) {
cin >> a >> b >> w;
if (Map.find(a)==Map.end()) {//建立映射关系
idx[cnt] = a;
Map[a] = cnt++;
}
if (Map.find(b) == Map.end()) {
idx[cnt] = b;
Map[b] = cnt++;
}
weight[Map[a]] += w;
weight[Map[b]] += w;
unit(Map[a], Map[b]);//并查集
}
vector<int> team;//保存团伙
vector<gang> last;//保存团伙的首领
for (int i = 0; i < cnt; i++) {
if (tree[i] == -1) {
team.push_back(i);
}
}
for (int i = 0; i < team.size(); i++) {
int no; int max_w = 0;//no是团伙首领的编号 max_w用于保存目前团伙成员中最大的权重
int num = 0; int all = 0;//num是团伙中成员的数量 all是整个团伙的权重
for (int j = 0; j < cnt; j++) {
if (findroot(j) != team[i])continue;
num++; all += weight[j];
if (max_w < weight[j]) {
max_w = weight[j]; no = j;
}
}
if (num > 2 && all / 2 > k) {//满足题目要求
gang a; a.name = idx[no]; a.size = num;
last.push_back(a);
}
}
sort(last.begin(), last.end());//按照要求排序
cout << last.size() << endl;
for (int i = 0; i < last.size(); i++) {
cout << last[i].name << " " << last[i].size << endl;
}
}
return 0;
}

本文介绍了一种算法,通过分析电话记录来识别犯罪团伙及其头目。利用并查集和字符串映射,算法能准确找出通话时间超过设定阈值的团伙,并确定总通话时间最长的人为头目。
325

被折叠的 条评论
为什么被折叠?



