题目链接地址:
[https://pintia.cn/problem-sets/994805342720868352/problems/994805456881434624]
题目大意:
给出若干用户的通话记录,通话记录包括通话双方名字和通话时长。从通话记录中筛选出符合人数和总通话时长要求的群体,并输出群体中进行通话时长最多的人名字和群体中的人数。
解题思路:
本题采用并查集的解题思路。
主要数据结构:
设置结构体:
struct node
{
int w = 0;//用户的拨出记录。(拨出方最左边的名字)
int sum = 0;//用户的总通话记录。
int id;
}gn[MAXN];
设置三对映射:
map<string, int>idList;//名字对编号的映射
map<int, string>intToStr;//编号对名字的映射
map<string, int>ans;//符合条件的群体老大名字-群体人数的映射
vectorgang[MAXN];//存储以下标为群体老大编号的群体信息
程序代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<map>
using namespace std;
const int MAXN = 2020;
struct node
{
int w = 0;
int sum = 0;
int id;
}gn[MAXN];
map<string, int>idList;
map<int, string>intToStr;
map<string, int>ans;
vector<int>gang[MAXN];
int cnt = 1;
int father[MAXN] = { 0 };
void Union(int a, int b);//合并集合
void init();//初始化父亲数组
int findFather(int a);//找到父亲
int main() {
FILE*stream1;
freopen_s(&stream1, "Text.txt", "r", stdin);
init();
int n, tmpTime, k;
scanf("%d%d", &n, &k);
string str1, str2;
for (int i = 0; i < n; i++)
{
cin >> str1 >> str2 >> tmpTime;
if (idList.find(str1) == idList.end())//找不到对应的名字,则建立一个映射
{
intToStr[cnt] = str1;
idList[str1] = cnt++;
}
if (idList.find(str2) == idList.end())//找不到对应的名字,则建立一个映射
{
intToStr[cnt] = str2;
idList[str2] = cnt++;
}
int id1 = idList[str1], id2 = idList[str2];
gn[id1].sum += tmpTime;//累计用户的总通话时长
gn[id2].sum += tmpTime;//累计用户的总通话时长
gn[id1].w += tmpTime;//累计用户的拨出时长
Union(id1, id2);//两用户并集
}
for (int i = 1; i < cnt; i++)
{
gn[i].id = i;
gang[findFather(i)].push_back(i);//将i并入以i的父亲为群体头目的集合
}
for (int i = 1; i < cnt; i++)//遍历每一个用户
{
int len = gang[i].size();
if(len>2)//剔除用户少于2的群体
{
int maxSum = 0, callSum = 0, tmpID;
string head;
for (int j = 0; j < len; j++)//遍历以i为父亲的每一个群体成员
{
tmpID = gang[i][j];
if (gn[tmpID].sum > maxSum)
{
head = intToStr[gn[tmpID].id];
maxSum = gn[tmpID].sum;
}
else if (gn[tmpID].sum == maxSum)
{
string tmp = intToStr[gn[tmpID].id];
head = head < tmp ? head : tmp;
}
callSum += gn[tmpID].w;
}
if (callSum > k)
{
ans[head] = len;
}
}
}
printf("%d\n", (int)ans.size());
for (auto it = ans.begin(); it != ans.end(); it++)//输出
{
cout << it->first << " " << it->second << endl;
}
return 0;
}
void init() {
for (int i = 0; i <= MAXN; i++)
{
father[i] = i;
}
}
int findFather(int a) {
int x = a;
while (a != father[a])
{
a = father[a];
}
while (x != father[x])
{
int z = x;
x = father[x];
father[x] = a;
}
return a;
}
void Union(int a, int b) {
int af = findFather(a), bf = findFather(b);
if (af != bf)
{
if (gn[af].w > gn[bf].w)
{
father[bf] = af;
}
else
{
father[af] = bf;
}
}
}