#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;
int n, k;
unordered_map<string, vector<pair<string, int>>> g;
unordered_map<string, int> total; //所有人的通话总时间
unordered_map<string, bool> st; //判重数组,保证每个点只被搜索一次
int dfs(string ver, vector<string> &nodes)
{
st[ver] = true;
nodes.push_back(ver);
int sum = 0;
for (auto edge : g[ver])
{
sum += edge.second;
string cur = edge.first; //寻找与ver连通的边
if (!st[cur]) sum += dfs(cur, nodes);
}
return sum;
}
int main()
{
cin >> n >> k;
while (n -- )
{
string a, b;
int t;
cin >> a >> b >> t;
g[a].push_back({b, t}); //无向图相当于存两条有向边
g[b].push_back({a, t});
total[a] += t;
total[b] += t;
}
vector<pair<string, int>> res; ///string存头目的名字,int存团伙的人数
for (auto item : total) //遍历每个人
{
string ver = item.first;
vector<string> nodes; //存某个连通块里的所有人
int sum = dfs(ver, nodes) / 2;
if (nodes.size() > 2 && sum > k) //判断是否满足成为团队的条件
{
string boss = nodes[0]; //寻找总通话时间最长的人
for (string node : nodes)
if (total[boss] < total[node])
boss = node;
res.push_back({boss, (int)nodes.size()}); //把头目和团队人数存入答案数组
}
}
sort(res.begin(), res.end()); //对每个团伙按头目的字典序排序
cout << res.size() << endl; //输出答案数组的个数
for (auto item : res) cout << item.first << ' ' << item.second << endl;
//遍历答案数组,依次输出头目名和团队人数
return 0;
}
思路:
- 一个帮派就是一个连通块,该连通块最少有三个点,连通块所有边的长度大于阈值k
- 找连通块:图的搜索 DFS,同时要记录:总边权(判断是否大于k),所有点的名字(枚举所有点看哪个点的通话时间最久)
- 把无向边存储为两条有向边,故最后边权要除以2