转自scameeling的空间

http://hi.baidu.com/scameeling/item/b135831094ec756771d5e815

强连通分量 Kosaraju PK Tarjan

Kosaraju算法

对每个不在树中的点开始DFS一次,并记录离开各点的时间,这里是离开的时间,而不是到达时的,比如有图1->2 2->3 则1,2,3分别对应的时间是3 2 1,因为3没有出边,所以最先离开,其次是2,最后是1,

DFS后,在同一棵树中的点,如果dfn[v]>dfn[u]则说明点从v有可能到达u,而这棵树中的dfn[]最大的点,肯定可以到达每个点,从而在原图的逆图中,每次都选没有访问过的最大的dfn值开始DFS,如果可达点x 则说明它们是强连通的

void DFS_T(int u)
{
    int i,v;
    if(used[u])return ;
    used[u]=1;id[u]=scc;
    for(i=q[u];i!=-1;i=Tedge[i].pre)
    {
        v=Tedge[i].d;
        if(!used[v])DFS_T(v);
    }
}
void DFS(int v){
    int i,u;
    if(used[v])return ;
    used[v]=1;
    for(i=p[v];i!=-1;i=edge[i].pre)
    {
        u=edge[i].d;
        if(!used[u])DFS(u);
    }
    order[++num]=v;
}
int Kosaraju()
{
    int i,j,k,v,u;
    memset(used,0,sizeof(used));num=0;
    for(i=1;i<=n;++i)if(!used[i])DFS(i);
    memset(used,0,sizeof(used));
    memset(id,0,sizeof(id));scc=0;
    for(i=num;i>=1;--i)if(!used[order[i]])scc++,DFS_T(order[i]);

}

Tarjan算法

dfn[v] 记录到达点v的时间,跟上面的离开不同,low[v]表示通过它的子结点可以到达的所有点中时间最小值,即 low[i]=min(low[i],low[u]),u为v的了孙,初始化时low[v]=dfn[u]。如果low[v]比dfn[v]小,说明v可 以通过它的子结点u,u1,u2...到达它的祖先v',则存在环,这个环上所有的点组成的子图便是一个强连通分量。换一个角度看,如果当 low[v]==dfn[v]时,则它的子树中所有low[u]==dfn[v]的点都与v构成一个环,维护一个栈,DFS过程中,每遍历一个点则把它放 入栈中,当发现low[v]==dfn[v]则依次把栈里的元素都弹出来,当栈顶元素为v时结束,这些点便构成一个以v为树根的强连通分量。

仍以上图为例,首先遍历点1,并dfn[1]=low[1]=++num, num表示按先后访问时间编号 ,同时1入栈

a.从3深入 dfn[3]=low[3]=2; 3入栈

b.从3到5 dfn[5]=low[5]=3; 5入栈

c.从5到6 dfn[6]=low[6]=4; 6入栈

d.发现6没有子结点可走,这时判断dfn[6]==low[6],于是开始弹栈,当遇到6时则break,即共弹出一个元素,于是6便是一个强连通分量

e.回溯至5,同样判断和弹栈,发现5也是一个强连通分量

f.再回溯至3,发现有边3->4,dfn[4]=low[4]=5,4入栈

g.4有边到1,由于1已经在栈里面,所以用dfn[1]更新low[4] 即low[4]=min(low[4],dfn[1])=1

h.回溯更新4的父亲3的low值 low[3]=min(low[3],low[4])=1

i.再回溯至1,发现有边1->2 继续深度遍历,2入栈,发现它的子结点4已经在栈中,直接更新low[2]=min(low[2],dfn[4]);

j.回溯至1,从而1所有出发的边都走了一遍,这时再比较low[1]与dfn[1],发现相等,于是开始弹栈,找到2,4,3,1这四个元素,构成一个连通分量。

void Tarjan(int v){
    dfn[v]=low[v]=++num;
    used[v]=1;
    st[++numSt]=v;
    for(int i=p[v];i!=-1;i=edge[i].pre){
        int u(edge[i].d);
        if(!dfn[u])//还没有标号的点
        {
            Tarjan(u);//先遍历它的子结点
            GetMin(low[v],low[u]);//用子结点更新当前点的low值
        }
        else if(used[u]&&GetMin(low[v],dfn[u]));
    }
    if(dfn[v]==low[v]){
        scc++;
        while(1){
            int u(st[numSt--]);
            id[u]=scc;
            used[u]=0;
            if(v==u)break;
        }
    }
}

int main(){

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

}

转载于:https://www.cnblogs.com/Yu2012/archive/2012/07/30/2615189.html

强连通分量 Kosaraju PK Tarjan(转)相关推荐

  1. HDU2767(强连通分量+Kosaraju算法)

    题意:需要加多少边才能把一个图变成强连通分量 强连通图:在有向图中,任意节点除法都可以到达其余所有节点,则称为强连通图. 强连通分量:在非强连通图的有向图中,选取部分点为强连通图,该强连通子图称为强连 ...

  2. 打印有向图的强连通分量-----kosaraju算法(最简单的实现)

    一.kosaraju算法步骤: 1.首先对图G进行一次DFS,记录每个顶点完成的顺序(DFS树/林的叶子节点先完成,然后回溯到它双亲这一层,它个双亲递归遍历完自己的邻居并在这些递归完成回溯到这层后,它 ...

  3. HDU4635(强连通分量+Kosaraju算法)

    题意:给出一个有向图,最多添加多少条边使这个图依然不是强连通图:当这个图是强连通图时,输出-1: 求解思路:强连通分量求解: 强连通图:在有向图中,任意节点除法都可以到达其余所有节点,则称为强连通图. ...

  4. 有向图最长路径算法_算法数据结构 | 三个步骤完成强连通分量分解的Kosaraju算法...

    强连通分量分解的Kosaraju算法 今天是算法数据结构专题的第35篇文章,我们来聊聊图论当中的强连通分量分解的Tarjan算法. Kosaraju算法一看这个名字很奇怪就可以猜到它也是一个根据人名起 ...

  5. 图论 —— 图的连通性 —— Tarjan 求强连通分量

    [概述] Tarjan 算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树. 搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量. [ ...

  6. codeforce 427 C. Checkposts(tarjan 强连通分量)

    题目链接:http://codeforces.com/contest/427/problem/C 题目大意是有n个junctions,这些junctions之间有m条道路,两两相连,现在在juncti ...

  7. tarjan算法求解强连通分量问题

    Part1:有向图的强连通分量: 一个连通图只有一个联通分量就是自身,非连通图有多个连通分量. 在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从v ...

  8. 强连通分量——tarjan算法缩点

    一. 什么是强连通分量? 强连通分量:在有向图G中,如果两个顶点u,v间(u->v)有一条从u到v的有向路径,同时还有一条从v到u的有向路径,则称两个顶点强连通(strongly connect ...

  9. 图论之tarjan真乃神人也,强连通分量,割点,桥,双连通他都会

    先来%一下Robert Tarjan前辈 %%%%%%%%%%%%%%%%%% 然后是热情感谢下列并不止这些大佬的博客: 图连通性(一):Tarjan算法求解有向图强连通分量 图连通性(二):Tarj ...

最新文章

  1. 设置tabbaritem的title的颜色及按钮图片
  2. 再谈编程范式-程序语言背后的思想
  3. 堆(heap)和栈(stack)的区别
  4. PowerBI Report Server 自定义视图无法显示故障解决
  5. 分段函数返回字符c语言,C++对cin输入字符的判断及分段函数处理方法示例
  6. vue-cli的webpack模板项目配置文件说明
  7. debian 配置linuxptp 软件时间戳
  8. shell脚本编写_shell脚本编写事例(dhcp自动安装和自动配置)
  9. 灰度直方图匹配(灰度直方图规定化)matlab代码
  10. matlab导出prn文件怎么打开,prn文件怎么打开?prn是什么意思?
  11. python提取cad坐标_从CAD图里提取坐标的方法
  12. 向量空间模型算法(Vector Space Model)
  13. InsecureProgramming-master——abo3
  14. Azure CDN 服务详解
  15. c语言scanf_s函数详解,scanf_s()函数
  16. 苹果虚拟home键_苹果手机几个实用小技巧,相见恨晚,快试试你的手机!
  17. Windows 程序设计作者
  18. 可可粉的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  19. TOP Network 2019年度回顾:积蓄力量,再创辉煌
  20. Android aab的打包、调试、安装

热门文章

  1. 全阶滑模观测器程序_滑模观测器转子估算程序
  2. tomcat 占用的内存越来越大_智能手机内存为什么越来越大 就这三点原因
  3. qcustomplot删除一条曲线_被“谭卓”旗袍造型给惊艳,波波头搭配一条酒红色旗袍,华丽高贵...
  4. PostgreSQL主备切换
  5. 3-5Tensor的属性
  6. Python机器学习:评价分类结果004F1score
  7. Python机器学习:KNN算法03训练数据集,测试数据集train test split
  8. java异常处理思考题_java异常处理试题及答案
  9. 计算机office2010高级应用程序,计算机办公软件应用office2010高级解题步骤
  10. sudu在linux的命令,sudo命令