ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

tarjan强连通--zhengjun

2022-06-11 14:01:27  阅读:158  来源: 互联网

标签:tarjan 一个点 搜到 -- 可以 连通 zhengjun int low


强连通就是在一个有向图中任何一个点都可以到达除这个点之外的所有点。

然后,在处理的时候,就可以把这一个子图直接变成一个点。

比如说这张图

A_zjzj
就可以缩成这张图
A_zjzj

原图中的
A_zjzj
就是一个强连通

也就是说只要有环,就一定有一个强连通(其实自己一个也算一个强连通)

然后,就是找环的环节~~~~重点

找环,其实就是看看可不可以搜到之前被搜到的点。可是,如果有一个大环套了一个小环,而我们却先搜到了这个小环,那么搜完了之后还是要继续搜下面的点,也就是说,我们一定要把这个点之后的点都搜完了之后才可以下结论。

所以我们可以用\(low_i\)表示\(i\)这个点最多可以上到之前搜到过的哪一个点,这样,如果\(low_i\)不是他自己,那么这里一定有一个环——强连通分量。

那么,要求出\(low_i\),就是最多能上到之前搜到过的哪一个点,就应该记录搜到这个点的顺序,存在\(dfn\)中,然后,就可以直接取\(\min\)就好了。

另外,如果现在找到了一个点的\(dfn_i\ne low_i\),那么它刚才搜了一圈的点都可以变成一个强连通,所以,就可以用一个队列来存储刚刚搜过的点,直接把队列中的数知道这个店取出来变成一个强连通就可以了。

代码

int min(int x,int y){return x<y?x:y;}
int n,m;
struct zj{
    int to,nex;
}e[maxm];
int k,head[maxn];
void add(int x,int y){
    e[++k]=(zj){y,head[x]};head[x]=k;
}
int dfn[maxn],low[maxn],stack[maxn],top,scc[maxn],scct,cnt;
void tarjan(int x){
    dfn[x]=low[x]=++cnt;//开始时一个点对多能达到的点就是他本身
    stack[top++]=x;//进入队列
    for(int i=head[x];i;i=e[i].nex){
        int v=e[i].to;
        if(!dfn[v]){//这个点还没有搜过
            tarjan(v);//继续搜这个点
            low[x]=min(low[x],low[v]);//取最小值
        }
        else if(!scc[v])low[x]=min(low[x],low[v]);//注意要下一个点没有成为一个强连通才可以
    }
    if(dfn[x]==low[x]){//有一个强连通
        scct++;//强连通的序号
        while(stack[top-1]!=x){//出队
            scc[stack[top-1]]=scct;
            top--;
        }
        scc[stack[top-1]]=scct;//剩下最后一个他自己
        top--;
    }
}

标签:tarjan,一个点,搜到,--,可以,连通,zhengjun,int,low
来源: https://www.cnblogs.com/A-zjzj/p/16365760.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有