算法随笔——tarjan
随便记点
链接
有向图求强连通分量(SCC)
SCC 定义:任意两个点都可以互相到达的子图。
一张图中每个节点只属于一个 SCC。
dfs 过程中维护一个栈,表示当前可能凑成一个 SCC 的元素。
具体过程
- dfs,x 被第一次访问,
,入栈 - 扫描出边 (x,y),
- y 没被访问,
——根据定义可知。 - y 访问过且于栈内(即不属于任何一个SCC,
- y 没被访问,
- 扫描完后,若有
,说明子树出现横叉边,与 x 构成了环。则栈顶一直到 之间的元素为一个 。
缩点
可以将每一个
值得注意的是建
重要结论!!!
代码中
因此有的时候跑完 tarjan 并不需要在跑一次 topo
非常的牛。
code
void tarjan(int u)
{
dfn[u] = low[u] = ++tot;
sta.push(u);ins[u] = 1; //标记是否在栈中
for (auto j : v[u])
{
if (!dfn[j]) tarjan(j),low[u] = min(low[u],low[j]);
else if (ins[j]) low[u] = min(low[u],dfn[j]);
}
if (low[u] == dfn[u])
{
cnt ++;
int cur;
do
{
cur = sta.top();
scc[cnt].push_back(cur),sta.pop();ins[cur] = 0;
id[cur] = cnt;
}while (cur != u);
}
}
for (int i = 1;i <= n;i++) if (!dfn[i]) tarjan(i); //图可能不联通
for (int i = 1;i <= n;i++)
for (auto j : v[i])
if (c[i] != c[j]) v2[c[i]].push_back(c[j]);
无向图求联通分量
边双连通分量
相当于把图上的桥去掉。
判定方法:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)