tarjan复习小结

虽然是复习,但还是学到许多。

tarjan求强连通分量

基础知识

过程中遇到四种边
1>树枝边:(dfs)搜索树上的边 满足边((u,v) ,v)不在栈中 (u)(v)的父节点
2>前向边:与(dfs)方向一致 祖先指向子孙 没什么用
3>后向边:与(dfs)方向相反 子孙指向祖先 满足边((u,v)). (v)在栈中,(u)(v)的祖先节点
4>横叉边:从某个结点指向搜索树中另一子树中某结点的边 满足边((u,v)), (v)在栈中 (u)不为(v)的祖先节点

定义两个数组(dfn)(low)(dfn[x])表示(x)节点是第几个被遍历到的。(low[x])表示(x x)以及它的所有子树的出边的(dfn)的最小值,由定义可以得出:

如果((u,v))是树枝边 (low[u]=min(low[u],low[v]))
如果是横叉边或后向边 (low[u]=min(dfn[v],low[u]))

当结点(u)的搜索过程结束之后,若(dfn[u] == low[u]) 则以(u)为根的搜索子树上所有还在栈中的结点,是一个强连通分量,可退栈,为什么呢????
我也不知道

通俗的说,若(u)为强连通分量的根,那么它的子孙中的最高祖先应该是它本身。

算法流程

数组的初始化,当首次到达(u)这个点时,更新(low)(dfn)的值, 将(u)入栈
更新(low[u])
如果((u,v))是树枝边 (low[u]=min(low[u],low[v]))
如果是横叉边或后向边 (low[u]=min(dfn[v],low[u]))

如果u的子树全被遍历完,(low[u] == dfn[u])那么退栈,退到(u)退出,这些退出的元素就是一个强连通分量。

因为图有可能有好几个部分,也就是说,(tarjan)图不连通。那么我们还要继续搜索,直到所有点都被遍历

code

void tarjan(int x) {
    low[x] = dfn[x] = ++cnt, sta[++top] = x, vis[x] = 1;
    for (int i = head[x]; i; i = edge[i].next) {
        int to = edge[i].to;
        if (!dfn[to]) tarjan(to), low[x] = min(low[x], low[to]);
        else if (vis[to]) low[x] = min(dfn[to], low[x]);
    }
    if (dfn[x] == low[x]) {
        num++;
        while (x != sta[top + 1]) {
            vis[sta[top]] = 0;
            top--;
        }
    }
}

for (int i = 1; i <= n; i++)
    if (!dfn[i]) tarjan(i); 

模型建立

其实就是缩点,要不然也没别的用处。

因为每一个强连通分量中的点都是相互可达的,我们可以将当前这个强连通分量缩成一个点,这个点的权值由题目来定(通常会有强连通分量中的点权和或者点权的最小值)

我们用到染色的思想,因为退栈的时候退栈的所有元素都是同一个强连通分量中的,所以我们可以在这个时将所有的点都染成同一种颜色,同时处理缩完点之后点的权值。

code

void tarjan(int x) {
    low[x] = dfn[x] = ++cnt, sta[++top] = x, vis[x] = 1;
    for (int i = head[x]; i; i = edge[i].next) {
        int to = edge[i].to;
        if (!dfn[to]) tarjan(to), low[x] = min(low[x], low[to]);
        else if (vis[to]) low[x] = min(dfn[to], low[x]);
    }
    if (dfn[x] == low[x]) {
        num++;
        while (x != sta[top + 1]) {
            vis[sta[top]] = 0;
            col[sta[top]] = num;
            val[num] += a[sta[top]];
            top--;
        }
    }
}

例题

间谍网络
稳定婚姻
消息扩散
HXY烧情侣
受欢迎的牛
校园网
最大半连通子图
网络协议
消息的传递
间谍网络

tarjan求割点或桥

原文地址:https://www.cnblogs.com/zzz-hhh/p/13453765.html