当前位置: 首页 > news >正文

有向图强连通分量

相关定义

若有向图的 \(u, v\) 两点互相可达,则称 \(u, v\) 强连通。满足任意两点强连通的有向图为 强连通图。有向图的极大强连通子图称作 强连通分量(SCC)

以下讨论时默认图为有向弱连通图(弱连通即将有向边看作无向边时连通)。

DFS 树

对于有向图,按照任意顺序对结点进行 DFS,得到 DFS 森林,DFS 树上的点称作树边。显然每棵 DFS 树内部的结点不强连通。

定义 DFS 树中从祖先指向后代的非树边,称为 前向边;从后代指向祖先的非树边为 返祖边;两端无祖先后代关系的边为 横叉边

前向边不影响可达性。返祖边 \((u, v)\) 会使得 \(v\)\(u\) 路径上的所有点之间强连通,且返祖边会减少时间戳。

对于横叉边,显然应该有 \(dfn(v) < dfn(u)\),因此也减少时间戳。进一步,若 \(dfn(v) < dfn(u)\),则 \(v\) 可达 \(u\) 当且仅当 \(v\) 可达 \(\operatorname{lca}(u, v)\)

SCC 求法

\(dfn_u\) 为 dfs 序,\(low_u\)\(u\) 经过树边与返祖边能到达的最小时间戳。则当 \(dfn_u = low_u\) 时以 \(u\) 为根的 dfs 子树中的点构成一个强连通分量。

void tarjan(int u) {dfn[u] = low[u] = ++ timestamp;stk[++ top] = u, vis[u] = 1;for (auto v : G[u]) {if (!dfn[v]) {tarjan(v);low[u] = min(low[u], low[v]); } else if (vis[v]) low[u] = min(low[u], dfn[v]);}if (low[u] == dfn[u]) {++ scnt; int x; do {x = stk[top]; col[x] = scnt; top --; vis[x] = 0;} while (x != u); }
}

例题

P3387

我们将每个 SCC 缩成点,点权为 SCC 内部的点权和,进行拓扑排序 DP 即可。

注意到根据上述过程找出 SCC 后得到逆拓扑序,所以不用特别再处理了。

P3436

如果存在自环切该点能够到达 \(n + 1\) 答案有 \(\infty\) 个。如果存在大小大于 \(1\) 的 SCC 连通 \(n + 1\) 那么 SCC 内的所有点答案都是 \(\infty\)

边 DP 求答案边找这个即可。

P7737

一个强连通分量中的点显然可以互相到达,所以先缩点,缩成一个 DAG。

会发现 DAG 其实不是很好做,考虑题目给出的特殊结构,若 \(x \to z, y \to z\),则存在 \(x \to y\)\(y \to x\)。会发现这样就能消掉一条边,构造出一个叶向树。

观察一下这个叶向树。称一个询问给出的 \(2(k + 1)\) 个点为特殊点,对于叶向树上的一个点,它能到达的充要条件是在祖先与后代中分别存在可以从 \(s\) 到达也可以到达 \(t\) 的特殊点,称这些特殊点为关键点。

由于 \(k\) 特别小,所以直接暴力找即可。统计答案考虑用虚树维护,在栈中维护一个点均为关键点的序列,就可以统计答案了。

代码挺难写。

其实还有更魔怔的做法用树剖和珂朵莉树维护这个东西。

AT_arc092_d

在机房电脑上。

CF1361E

这种题显然要先考虑如何判定一个点是否合法。会发现一个点合法当且仅当以这个点为根的 DFS 树上不存在横叉边与前向边。

考虑找到一个合法点后如何判定其它点是否合法。由于我们图上只存在返祖边,所以只需要考虑返祖边的影响。

对于一条返祖边 \((u, v)\) 相当于覆盖了 \(v \to u\) 路径上的所有点(不包括 \(v\)),对于一个点 \(x\),如果被超过一条返祖边覆盖,则一定不合法。

于是考虑树上差分即可。现在问题是怎么找出一个合法点。

由于题目中说明存在 \(80 \%\) 的有趣城市,于是我们直接随机化找点就是对的。如果没找到说明不符合条件,输出 \(-1\)

http://www.wxhsa.cn/company.asp?id=4733

相关文章:

  • Kafka 消费者元数据topicId变化问题
  • 【SPIE出版】第五届生物医学与生物信息工程国际学术会议(ICBBE 2025)
  • Qoder 全新「上下文压缩」功能正式上线,省 Credits !
  • journald 持久化 + 限额脚本
  • 【2025-09-14】连岳摘抄
  • 深入解析:PAT乙级_1125 子串与子列_Python_AC解法_含疑难点
  • ESP32-S3 与GPS北斗通信返回定位/海拔/速度数据的测试代码
  • GZY.Quartz.MUI(基于Quartz的UI可视化操作组件) 2.8.0发布 新增仪表盘和检索功能
  • AIGEO助力企业破局
  • 东南大学数据库课程06-Database Design
  • MacOS升级15.2后的问题(二):无法修改mac网络地址
  • 东南大学数据库课程07-Distributed Database Systems
  • HCIA——VLAN间通信
  • Xdebug安装与PhpStorm调试配置
  • vue - 内置指令
  • 东南大学数据库课程02-DataModel数据模型
  • Torch核心数据结构Tensor(张量)
  • vue - 进阶
  • 读书笔记:为什么你的数据库有时不用索引?一个关键参数告诉你答案
  • MacOS升级15.2后的问题(一):安装第三方下载的软件,提醒文件已损坏
  • Playwright MCP浏览器自动化教程
  • 故障分析:ORA-00900 修改props$中字符集导致
  • 实用指南:Flask学习笔记(三)--URL构建与模板的使用
  • Ollama + Python 极简工作流
  • 快速搞定Dify+Chrome MCP:打造能操作网页的AI助手
  • HCIP——RSTP
  • ORA-01555系列:三、ORA-01555总结与高级优化建议
  • Unstable Twin - TryHackMe
  • 单片机实现挡位调节
  • 完整教程:从 WildCard 野卡到 gptplus.plus:一次解决 OpenAI 支付难题的实战复盘,轻松搞定Gpt充值