码迷,mamicode.com
首页 > 其他好文 > 详细

关于tarjan

时间:2019-03-19 21:37:32      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:替换   情况下   else   拓扑   问题   机房   code   最小   for   

关于Tarjan算法

梗概

tarjan算法有两种(我了解的),一种是用来求强连通分量的,另一种是关于割点和桥的问题。

根据机房大佬HL说过,这两种算法是互相独立的,只是代码很像。


强连通分量问题

关于这类tarjan算法,我了解到的主要的一个应用就是缩点。

例题传送门

思路

首先,如果我们考虑,如果这是一个有向无环图,我们可以用拓扑排序(DP?)的方法直接求出答案。

但是这个图是一个有向有环图,无法直接采用拓扑排序。

这时候我们想为什么无法直接用拓扑排序,因为在有环的情况下我们无法直接确定各个点的拓扑序。

如果我们把每个环都替换成一个点,点权为环中点权的总和,这就是一个有向无环图。

怎么样才可以找到这些环呢?这时候就可以拿出tarjan了。

tarjan算法

tarjan算法有两个关键的数组:dfn[]和low[]。

dfn[i]表示搜索到第i个点时的时间戳(第几个搜到的)。

low[i]表示第i个点所在的环中的所有点的最小dfn[]。

上代码:

void dfs(int x){
    dfn[x]=low[x]=++Tt;q[++t]=x;vis[x]=1;//Tt为时间戳 q[]为栈数组
                                        //vis[i]表示i点是否在栈中
    for(int i=lnk[x];i;i=la[i]){
        int y=ne[i];
        if(!dfn[y]){dfs(y);low[x]=min(low[x],low[y]);}
        //如果该节点没被遍历过,就查看x是否与y在同一个环中。
        else if(vis[y])low[x]=min(low[x],dfn[y]);
          //否则,就查看x与y是否成环。
    }
    if(low[x]==dfn[x]){
        ++cnt;
        int y=0;
        while(y!=x){y=q[t];ty[y]=cnt;A[cnt]+=a[y];vis[y]=0;--t;}
      //这里为染色的过程,所有环都有一个颜色,后面根据每个点的颜色重新建图。
    }
}

关于tarjan

标签:替换   情况下   else   拓扑   问题   机房   code   最小   for   

原文地址:https://www.cnblogs.com/ADMAN/p/10561435.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!