博客
关于我
程序设计基础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 DBA 高级运维学习之路-DQL语句之select知识讲解
    查看>>
    mysql deadlock found when trying to get lock暴力解决
    查看>>
    MuseTalk如何生成高质量视频(使用技巧)
    查看>>
    mutiplemap 总结
    查看>>
    MySQL DELETE 表别名问题
    查看>>
    MySQL Error Handling in Stored Procedures---转载
    查看>>
    MVC 区域功能
    查看>>
    MySQL FEDERATED 提示
    查看>>
    mysql generic安装_MySQL 5.6 Generic Binary安装与配置_MySQL
    查看>>
    Mysql group by
    查看>>
    MySQL I 有福啦,窗口函数大大提高了取数的效率!
    查看>>
    mysql id自动增长 初始值 Mysql重置auto_increment初始值
    查看>>
    MySQL in 太多过慢的 3 种解决方案
    查看>>
    MySQL InnoDB 三大文件日志,看完秒懂
    查看>>
    Mysql InnoDB 数据更新导致锁表
    查看>>
    Mysql Innodb 锁机制
    查看>>
    MySQL InnoDB中意向锁的作用及原理探
    查看>>
    MySQL InnoDB事务隔离级别与锁机制深入解析
    查看>>
    Mysql InnoDB存储引擎 —— 数据页
    查看>>
    Mysql InnoDB存储引擎中的checkpoint技术
    查看>>