强连通:在有向图G中,两个顶点间至少存在一条路径,则两个点强连通。

强连通图:在有向图中,每两个顶点都强连通,则有向图G就是一个强连通图。

强连通分量:在非强连通图中的极大强连通子图,就称为强连通分量。

直接根据定义,可以通过双向遍历取交集的方法求强连通分量,但是其复杂度为O(N^2+M)。更好的方法是用tarjan算法,其时间复杂度为O(N+M)。

tarjan:其实就是对图的深度优先遍历。

算法模拟:

定义 DFN [u]为节点u被搜索到时的次序编号(也就是所遍历的第几个);

定义LOW[U]为U或者U 的子数能够追溯到最早的栈中节点的次序号。

  (当DFN[U] ==  LOE[U] 时,以U为根的搜索子树上所有节点是一个强连通分量。实质上就是这个点的整个子树回溯完了,没有链接的路了)

此时的F点DNF[F]==LOW[F]=4,所以F为一个强连通分量,只有它自己本身。

然后返回节点E,此时发现 DFN[E] == LOW[E] =5,所以E也单独为一个强连通分量,只有他本身。

然后返回节点C:

从C节点继续搜其他的C的子树,搜到节点D,将D加入栈中。然后D有  D ->  F ,但是F 已经出栈,所以F节点直接跳过,

还有一个节点A , 但是呢,A节点已经在栈中,所以LOW[D] = DFN[A] = 1,然后是一个回溯的过程,所以呢,LOW[C] = LOW [D] =1;

所以说明这三个节点已经是一个强连通分量了。

继续回到节点A,最后访问B节点,,然后 B-> D ,然而 D点还在栈中,所以LOW[B] = DFN [ D ] = 5 ,DFN[B] = 6 ;

没有其他点了,算法结束,最后得到 {A,B,C,D} ,{E}, {F}为强连通分量。

在tarjan算法中,每个点只被访问了一次,而且只进行了一次的栈,每条边也只被访问了一次,。所以该算法的时间复杂度为O(N+M);

程序模板:

 #include <cstdio>
#include <cstring>
#include <iostream>
using namespace std; #define N 100
#define M 100 struct node
{
int v;
int next;
}; node edge[M];//边的集合 int a[N];//顶点的集合
int instack[N];//模拟栈,标记是否在栈中
int stack[N];
int belong[N];//各个顶点属于哪个强连通分量
int DFN[N];
int LOW[N];//栈中能够追溯到最早的节点序号
int n;//点的个数
int m;//边的个数
int count;//边的计数器
int index;//序号(时间戳)
int top;
int sun;//强连通分量的个数 //用邻接表存储
void add_edge(int u,int v)
{
edge[count].next=a[u];
edge[count].v=v;
a[u]=count++;
} void tarjan(int u)
{
int i,j;
int v;
DFN[u]=LOW[u]=++index;
instack[u]=true;
stack[++top]=u;//进栈
for(i=a[u];i!=-;i=edge[i].next)
{
v=edge[i].v;
if(!DFN[v])//如果DFN[v]为0,没被访问
{
tarjan(v);
//一个回溯的过程
if(LOW[v]<LOW[u])
LOW[u]=LOW[v];
}
else
{
if(instack[v]&&DFN[v]<LOW[u])
LOW[u]=DFN[v];
}
}
if(DFN[u]==LOW[u])
{
sun++;
//出栈
do
{
j=stack[top--];
instack[j]=false;
belong[j]=sun;
}while(j!=u); }
} void solve()
{
int i;
top=index=sun=;
memset(DFN,,sizeof(DFN));
memset(LOW,,sizeof(LOW));
for(i=;i<=n;i++)
{
if(!DFN[i])
tarjan(i);
}
} int main()
{
int i,j,k;
count=;
memset(a,-,sizeof(a));
scanf("%d %d",&n,&m);
for(i=;i<=m;i++)
{
scanf("%d %d",&j,&k);
add_edge(j,k);
}
solve();
for(i=;i<=n;i++)
printf("%d ",belong[i]);
}

tarjan有向图的强连通的更多相关文章

  1. HDU1269迷宫城堡(裸Tarjan有向图求强连通分量个数)

    迷宫城堡Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...

  2. 『Tarjan算法 有向图的强连通分量』

    有向图的强连通分量 定义:在有向图\(G\)中,如果两个顶点\(v_i,v_j\)间\((v_i>v_j)\)有一条从\(v_i\)到\(v_j\)的有向路径,同时还有一条从\(v_j\)到\( ...

  3. UVA247- Calling Circles(有向图的强连通分量)

    题目链接 题意: 给定一张有向图.找出全部强连通分量,并输出. 思路:有向图的强连通分量用Tarjan算法,然后用map映射,便于输出,注意输出格式. 代码: #include <iostrea ...

  4. HDU 1269 迷宫城堡 tarjan算法求强连通分量

    基础模板题,应用tarjan算法求有向图的强连通分量,tarjan在此处的实现方法为:使用栈储存已经访问过的点,当访问的点离开dfs的时候,判断这个点的low值是否等于它的出生日期dfn值,如果相等, ...

  5. Tarjan算法分解强连通分量(附详细参考文章)

    Tarjan算法分解强连通分量 算法思路: 算法通过dfs遍历整个连通分量,并在遍历过程中给每个点打上两个记号:一个是时间戳,即首次访问到节点i的时刻,另一个是节点u的某一个祖先被访问的最早时刻. 时 ...

  6. 图->连通性->有向图的强连通分量

    文字描述 有向图强连通分量的定义:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly co ...

  7. DFS的运用(二分图判定、无向图的割顶和桥,双连通分量,有向图的强连通分量)

    一.dfs框架: vector<int>G[maxn]; //存图 int vis[maxn]; //节点访问标记 void dfs(int u) { vis[u] = ; PREVISI ...

  8. uva11324 有向图的强连通分量+记忆化dp

    给一张有向图G, 求一个结点数最大的结点集,使得该结点集中任意两个结点u和v满足,要么u可以到达v, 要么v可以到达u(u和v相互可达也可以). 因为整张图可能存在环路,所以不好使用dp直接做,先采用 ...

  9. 图论-求有向图的强连通分量(Kosaraju算法)

    求有向图的强连通分量     Kosaraju算法可以求出有向图中的强连通分量个数,并且对分属于不同强连通分量的点进行标记. (1) 第一次对图G进行DFS遍历,并在遍历过程中,记录每一个点的退出顺序 ...

随机推荐

  1. Struts2实现空表单信息的提示

    须要的jar包文件: index.jsp源代码: <%@ page language="java" contentType="text/html; charset= ...

  2. 读书笔记-2java虚拟机的可达性算法与finalize方法

    JAVA通过可达性分析算法来确定堆中哪些对象是应该被回收的. 非常多人包含我曾经在不了解的时候总以为是通过引用计数器来推断某个对象是否应该被回收可是后来想了想包含查阅一些资料发现不是这种.由于假设採用 ...

  3. Nova镜像使用方法

    Nova中的虚拟机可以从镜像.卷.卷快照等启动,一般装完OpenStack时,环境中既没有镜像也没有卷,这时候往往 需要上传一些已有的镜像,或者上传ISO文件来安装虚拟机系统.这个文档主要描述如何上传 ...

  4. Mysql 数据库中间件

    读写分离:简单的说是把对数据库读和写的操作分开对应不同的数据库服务器,这样能有效地减轻数据库压力,也能减轻io压力.主数据库提供写操作,从数据库提供读操作,其实在很多系统中,主要是读的操作.当主数据库 ...

  5. Redis实现分布式锁(Set和Lua)

    转载:https://www.cnblogs.com/linjiqin/p/8003838.html 前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于Z ...

  6. 2016/06/13 phpexcel 未完待续

    ①准备工作: 1,php版本不能太低 2,去官网下载PHPExcel插件    http://phpexcel.codeplex.com/ 3,解压后提取classes文件夹到工作目录,并重命名为PH ...

  7. CentOS 6.5 通过 PHP函数的sendmail 发送邮件

    非常多站点须要用到Sendmail函数发送激活邮件,在centos中内置了Sendmail模块,直接调用就可以,假设遇到问题,可採用例如以下两个步骤检測并解决: 1. 命令行输入:echo " ...

  8. 基于Ubuntu 14.04 LTS编译Android4.4.2源码

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/gobitan/article/details/24367439 基于Ubuntu 14.04 LTS ...

  9. VC实现趋势图绘制

    本文参考pudn上一个完整工程,在pudn搜索“50815867CurveDrawing”即可找到源代码.   上图是使用VS2010重写了该软件后的效果图,下面再贴出关键代码: // Plot.cp ...

  10. About "self"

    Class method can't refer derectly to instance variables. Within the body of  a class method, self re ...