• 图论(强联通分量)


    图论中,特别是在讨论有向图(Directed Graph)时,我们常常需要了解图的结构特性,比如强联通分量(Strongly Connected Components, SCC)。了解强联通分量中的各种边对于理解图的整体结构以及某些算法(如Tarjan's算法或Kosaraju's算法)是非常重要的。以下是对强联通分量及其边类型的解释:

    强联通分量(SCC)

    强联通分量是一个子图,其中每对顶点之间都有路径相互可达。换句话说,一个强联通分量内的任意两个顶点 u 和 v 都满足 u 到 v 和 v 到 u 之间存在路径。

    边的分类

    板子如下

    1. #include
    2. using namespace std;
    3. const int N = 1e5 + 10;
    4. vector<int> e[N]; // 存储图的邻接表
    5. int dfn[N], low[N]; // 存储每个节点的时间戳和最小到达时间
    6. bool ins[N]; // 标记节点是否在栈中
    7. int idx, bel[N], cnt; // 时间戳、节点所属的强联通分量编号、强联通分量计数
    8. stack<int> stk; // 用于 Tarjan 算法的栈
    9. vectorint>> scc;// 存储所有的强联通分量
    10. int n, m; // 节点数和边数
    11. void dfs(int u) {
    12. dfn[u] = low[u] = ++idx; // 初始化时间戳
    13. ins[u] = true; // 标记节点在栈中
    14. stk.push(u); // 将节点压入栈中
    15. for (auto v : e[u]) { // 遍历节点 u 的所有邻接点 v
    16. if (!dfn[v]) { // 如果节点 v 尚未访问
    17. dfs(v); // 递归访问节点 v
    18. low[u] = min(low[u], low[v]); // 更新节点 u 的最小到达时间
    19. } else if (ins[v]) { // 如果节点 v 在栈中
    20. low[u] = min(low[u], dfn[v]); // 更新节点 u 的最小到达时间
    21. }
    22. }
    23. if (dfn[u] == low[u]) { // 如果节点 u 是强联通分量的根节点
    24. vector<int> c; // 创建一个新的强联通分量
    25. ++cnt;
    26. while (1) {
    27. int v = stk.top(); // 弹出栈顶节点
    28. c.push_back(v); // 将节点添加到当前强联通分量中
    29. ins[v] = false; // 标记节点不在栈中
    30. bel[v] = cnt; // 标记节点所属的强联通分量编号
    31. stk.pop(); // 弹出栈顶节点
    32. if (u == v) break; // 如果节点 u 是栈顶节点,结束循环
    33. }
    34. sort(c.begin(), c.end()); // 对强联通分量内的节点排序
    35. scc.push_back(c); // 将强联通分量添加到结果中
    36. }
    37. }
    38. int main() {
    39. ios::sync_with_stdio(0);
    40. cin.tie(0);
    41. cin >> n >> m;
    42. for (int i = 1; i <= m; i++) {
    43. int u, v;
    44. cin >> u >> v;
    45. e[u].push_back(v); // 构建邻接表
    46. }
    47. for (int i = 1; i <= n; i++) {
    48. if (!dfn[i]) dfs(i); // 对每个未访问的节点进行 DFS
    49. }
    50. sort(scc.begin(), scc.end()); // 对所有的强联通分量排序
    51. cout << cnt << endl; // 输出强联通分量的数量
    52. for (auto c : scc) { // 输出每个强联通分量
    53. for (auto u : c) {
    54. cout << u << " ";
    55. }
    56. cout << endl;
    57. }
    58. return 0;
    59. }

    题目链接 洛谷 B3609

    参考文献 scc

  • 相关阅读:
    bazel构建cpp项目
    【JavaScript设计模式】增强版发布订阅模式——Webpack的核心Tapable(一)
    靠着数套的Java刷题PDF,成功“混进”腾讯T3
    电脑重装系统后内存占用高怎么解决?
    python Zipf定律-高度偏斜分布
    JAVA设计模式之模板方法模式
    零基础学ptyhon之字典
    敏捷管理的4价值观12准则
    gRPC-GateWay Swagger 实战
    SQL语言(二)数据更新
  • 原文地址:https://blog.csdn.net/weixin_59561323/article/details/140952461