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求割点或桥

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章