新冠疫情期间,大家不能聚会,于是姐妹们就开始煲电话。姐妹们互相煲电话,自然就成了一个一个的圈子,为了区分哪些是真闺蜜,哪些是塑料姐妹情,我们对电话记录进行了跟踪,通过分析通话时间来确定亲密程度。我们这样设定,两个人之间所有的电话时间长度之和作为两个人亲密度的度量,一个姐妹圈是由三个或三个以上的女生组成,且所有成员的通话时间之和超过某个阈值K,姐妹圈中通话时间最长的那个就是该圈的核心。现在给一些通话清单,请找出姐妹圈的个数和姐妹圈里的核心。
输入格式:
第一行两个不超过1000的正整数N和K,分别表示电话的通数和阈值。随后的N行,按以下格式给出电话情况:
name1 name2 time
name1和name2使用3位大写字母来表示一个女生,time为不超过1000的整数,表示两人之间的通话时长。
输出格式:
对每一组输入,在第一行输出姐妹圈的个数。随后输出每一个姐妹圈的大姐大以及人数,中间用空格分隔。我们假设每个姐妹圈里的大姐大是唯一的。输出应按照大姐大的姓名的字母序升序输出。
输入样例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
输出样例1:
在这里给出相应的输出。例如:
2
AAA 3
GGG 3
输入样例2:
在这里给出一组输入。例如:
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:
在这里给出相应的输出。例如:
0
解题
- 并查集
- Hash函数
- UnionSet时要将亲密度最大的作为根
- FindSet时将根与x比较交换根,使得亲密度最大的作为根
代码:
#include <iostream> //7-10 电话聊天姐妹圈 (25分)
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 17576; //26 ^ 3 = 17576
string revn[maxn];
bool vis[maxn];
int Set[maxn];
int Value[maxn]; //每个人的亲密度
int SumValue[maxn]; //集合的亲密度之和
int Hash(string name)
{
return (name[0] - 'A') * 26 * 26 + (name[1] - 'A') * 26 + (name[2] - 'A');
}
int FindSet(int x)
{
if(Set[x] < 0)
return x;
return FindSet(Set[x]);
}
void UnionSet(int R1, int R2) //并集时, 使亲密度最大的作为根
{
if(R1 == R2)
return;
if(Value[R1] < Value[R2]) //使R2为根
Set[R2] += Set[R1], Set[R1] = R2;
else //使R1为根
Set[R1] += Set[R2], Set[R2] = R1;
}
int main()
{
memset(Set, -1, sizeof(Set));
string name1, name2;
int N, K, time;
cin >> N >> K;
K <<= 1;
for (int i = 0; i < N; i++)
{
cin >> name1 >> name2 >> time;
int a = Hash(name1);
int b = Hash(name2);
vis[a] = vis[b] = true; //出现的顶点
revn[a] = name1, revn[b] = name2; //下标对应name
Value[a] += time, Value[b] += time; //更新单人的亲密度
/*调整Value最大的为根*/
int r1 = FindSet(a);
if(Value[r1] < Value[a])
Set[a] = Set[r1], Set[r1] = a, r1 = a;
int r2 = FindSet(b);
if(Value[r2] < Value[b])
Set[b] = Set[r2], Set[r2] = b, r2 = b;
UnionSet(r1, r2); //合并后的根
}
for (int i = 0; i < maxn; i++)
if(vis[i])
SumValue[FindSet(i)] += Value[i]; //计算每个姐妹圈的总通话时间
vector<int> v;
for (int i = 0; i < maxn; i++)
if(vis[i] && Set[i] <= -3 && SumValue[i] > K)
v.push_back(i);
cout << v.size() << endl;
for (int i = 0; i < v.size(); i++)
cout << revn[v[i]] << " " << -Set[v[i]] << endl;
system("pause");
return 0;
}
2668

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



