博客
关于我
程序设计基础81 图之无向图防止回头和访问通向已访问结点的路径
阅读量:387 次
发布时间:2019-03-05

本文共 2512 字,大约阅读时间需要 8 分钟。

为了解决这个问题,我们需要识别电话联系网络中的“团伙”(Gang),其中每个团伙中的成员通过电话联系,总联系时间超过阈值K,且成员数量超过2。团伙的头头是联系时间最长的成员。

方法思路

  • 图的表示:将电话联系视为无向图,每条边表示通话,边权重为通话时间。
  • 遍历连通块:使用深度优先搜索(DFS)遍历图中的每个连通块,计算每个连通块的总联系时间和成员数量。
  • 判断团伙:检查每个连通块的总联系时间是否超过K,且成员数量是否超过2。如果满足条件,记录该连通块的头头和成员数量。
  • 排序和输出:按头头的名字排序,输出结果。
  • 解决代码

    #include 
    #include
    #include
    #include
    #include
    #include
    using namespace std;struct Node { int id; int total;};void convert_name_to_id(map
    & name_to_id, string name) { if (name_to_id.find(name) == name_to_id.end()) { name_to_id[name] = name_to_id.size() + 1000; }}void dfs(int u, int &currentTotalTime, int &maxPerson, int &count, const vector
    >& adj, const map
    & id_to_name, vector
    & visited) { if (visited[u]) { return; } visited[u] = true; count++; if (PersonTimes[u] > maxPerson) { maxPerson = u; } for (int v = 0; v < max_n; v++) { if (!visited[v] && adj[u][v] > 0) { currentTotalTime += adj[u][v]; dfs(v, currentTotalTime, maxPerson, count, adj, id_to_name, visited); adj[u][v] = 0; // 防止重复处理边 } }}int main() { map
    name_to_id; map
    id_to_name; const int max_n = 2020; int N, K; vector
    > adj(max_n, vector
    (max_n, 0)); int PersonTimes[max_n] = {0}; vector
    visited(max_n, false); // 读取输入 scanf("%d %d", &N, &K); // 读取通话记录 for (int i = 0; i < N; i++) { string str1, str2, str3; scanf("%s %s %d", &str1, &str2, &str3); // 转换名字为id convert_name_to_id(name_to_id, str1); convert_name_to_id(name_to_id, str2); int u = name_to_id[str1]; int v = name_to_id[str2]; int time = str3 - '0'; // 更新邻接矩阵和邻接表 adj[u][v] += time; adj[v][u] += time; // 更新总联系时间 PersonTimes[u] += time; PersonTimes[v] += time; } // 遍历每个节点 vector
    gangs; for (int u = 0; u < max_n; u++) { if (visited[u]) { continue; } int currentTotalTime = 0; int maxPerson = u; int count = 1; vector
    current_visited(max_n, false); current_visited[u] = true; // 进行DFS dfs(u, currentTotalTime, maxPerson, count, adj, id_to_name, current_visited); // 检查条件 if (currentTotalTime > K && count > 2) { Node gang; gang.id = maxPerson; gang.total = count; gangs.push_back(gang); } } // 按名字排序 sort(gangs.begin(), gangs.end(), [](const Node& a, const Node& b) { return id_to_name[a.id] < id_to_name[b.id]; }); // 输出 cout << gangs.size() << endl; for (const auto& gang : gangs) { cout << id_to_name[gang.id] << " " << gang.total << endl; } return 0;}

    代码解释

  • 输入处理:读取输入数据,解析每个通话,更新邻接矩阵和总联系时间数组。
  • 名字映射:将每个名字转换为唯一的整数索引,便于图的表示。
  • DFS遍历:使用DFS遍历每个连通块,计算总联系时间和成员数量。
  • 团伙判断:检查连通块是否满足团伙条件,记录头头和成员数量。
  • 排序和输出:按头头名字排序,输出结果。
  • 通过这种方法,我们可以有效地识别和处理电话联系网络中的团伙,确保输出符合要求。

    转载地址:http://imlwz.baihongyu.com/

    你可能感兴趣的文章
    MySQL 中开启二进制日志(Binlog)
    查看>>
    MySQL 中文问题
    查看>>
    MySQL 中日志的面试题总结
    查看>>
    mysql 中的all,5分钟了解MySQL5.7中union all用法的黑科技
    查看>>
    MySQL 中的外键检查设置:SET FOREIGN_KEY_CHECKS = 1
    查看>>
    Mysql 中的日期时间字符串查询
    查看>>
    mysql 中索引的问题
    查看>>
    MySQL 中锁的面试题总结
    查看>>
    MySQL 中随机抽样:order by rand limit 的替代方案
    查看>>
    MySQL 为什么需要两阶段提交?
    查看>>
    mysql 为某个字段的值加前缀、去掉前缀
    查看>>
    mysql 主从
    查看>>
    mysql 主从 lock_mysql 主从同步权限mysql 行锁的实现
    查看>>
    mysql 主从互备份_mysql互为主从实战设置详解及自动化备份(Centos7.2)
    查看>>
    mysql 主从关系切换
    查看>>
    MYSQL 主从同步文档的大坑
    查看>>
    mysql 主键重复则覆盖_数据库主键不能重复
    查看>>
    Mysql 事务知识点与优化建议
    查看>>
    Mysql 优化 or
    查看>>
    mysql 优化器 key_mysql – 选择*和查询优化器
    查看>>