有向图强联通分量的Tarjan算法
算法内容
dfn[u]dfn[u]dfn[u] :节点 uuu 搜索的次序编号
low[u]low[u]low[u] :节点 uuu 或 uuu 的子树(经过最多一条后向边或栈中横叉边)能回溯到的最早的栈中节点的次序编号
void Tarjan(int u){
dfn[u]=low[u]=++idx;
ins[u]=true,stk[++top]=u;
for(int i=0;i<e[u].size();++i){
int v=e[u][i];
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(ins[v]) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
num[bel[u]=++sum]=1,ins[u]=false;
int v=-1;
while(v=stk[top--],v!=u){
++num[bel[v]=sum];
ins[v]=false;
}
}
}
POJ 2186
考虑将图中的强连通分量缩点后构造新图,答案就是出度为零的强连通分量里包含的点数,注意存在两个出度为零的强连通分量时则无解。
POJ 3180
本质上就是找包含点数大于等于 222 的强连通分量的个数。
POJ 1236
第一个问题就是求缩点后入度为零的强联通分量的个数。
第二个问题我们可以考虑树的情况,比较显然就是入度为零和出度为零的点数的最大值,考虑扩展到森林的情况,将第一个树的出度为零的点连入第二个树入度为零的点,依次类推,最后将最后一棵树连回第一棵树,可以证明这样需要的边数最少。
本文解析了Tarjan算法在寻找有向图的强联通分量中的应用,包括dfn和low数组的使用,以及POJ问题实例中的图压缩和强连通分量计数。重点讲解了如何通过算法实现缩点操作并解决不同问题场景下的计数问题。

630

被折叠的 条评论
为什么被折叠?



