#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
本文介绍了一种基于图论的团伙识别算法,通过深度优先搜索(DFS)遍历无向图,寻找满足特定条件的连通块,即所谓的团伙。算法首先读取节点数量和阈值k,然后输入节点间的连接及通话时间,存储为无向图。接着,遍历图中每个节点,使用DFS算法找出所有连通块,并计算连通块内边的总权重。如果连通块的大小超过3且总权重超过k,则将其认定为团伙。最后,确定团伙内的头目(通话时间最长者),并输出团伙的头目和人数。
376

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



