tarjan有向图的强连通
强连通:在有向图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有向图的强连通的更多相关文章
- HDU1269迷宫城堡(裸Tarjan有向图求强连通分量个数)
迷宫城堡Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- 『Tarjan算法 有向图的强连通分量』
有向图的强连通分量 定义:在有向图\(G\)中,如果两个顶点\(v_i,v_j\)间\((v_i>v_j)\)有一条从\(v_i\)到\(v_j\)的有向路径,同时还有一条从\(v_j\)到\( ...
- UVA247- Calling Circles(有向图的强连通分量)
题目链接 题意: 给定一张有向图.找出全部强连通分量,并输出. 思路:有向图的强连通分量用Tarjan算法,然后用map映射,便于输出,注意输出格式. 代码: #include <iostrea ...
- HDU 1269 迷宫城堡 tarjan算法求强连通分量
基础模板题,应用tarjan算法求有向图的强连通分量,tarjan在此处的实现方法为:使用栈储存已经访问过的点,当访问的点离开dfs的时候,判断这个点的low值是否等于它的出生日期dfn值,如果相等, ...
- Tarjan算法分解强连通分量(附详细参考文章)
Tarjan算法分解强连通分量 算法思路: 算法通过dfs遍历整个连通分量,并在遍历过程中给每个点打上两个记号:一个是时间戳,即首次访问到节点i的时刻,另一个是节点u的某一个祖先被访问的最早时刻. 时 ...
- 图->连通性->有向图的强连通分量
文字描述 有向图强连通分量的定义:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly co ...
- DFS的运用(二分图判定、无向图的割顶和桥,双连通分量,有向图的强连通分量)
一.dfs框架: vector<int>G[maxn]; //存图 int vis[maxn]; //节点访问标记 void dfs(int u) { vis[u] = ; PREVISI ...
- uva11324 有向图的强连通分量+记忆化dp
给一张有向图G, 求一个结点数最大的结点集,使得该结点集中任意两个结点u和v满足,要么u可以到达v, 要么v可以到达u(u和v相互可达也可以). 因为整张图可能存在环路,所以不好使用dp直接做,先采用 ...
- 图论-求有向图的强连通分量(Kosaraju算法)
求有向图的强连通分量 Kosaraju算法可以求出有向图中的强连通分量个数,并且对分属于不同强连通分量的点进行标记. (1) 第一次对图G进行DFS遍历,并在遍历过程中,记录每一个点的退出顺序 ...
随机推荐
- 写2个线程,其中一个线程打印1~52,另一个线程打印A~z,打印顺序应该是12A34B45C……5152Z
我写的 class LN { private int flag = 0; public static char ch = 'A'; public static int n = 1; public sy ...
- OpenStack源码系列---起始篇
近一年来我负责公司云点的自动化部署工作,包括公司自有云平台方案.XenServer.vSphere.Ovirt和OpenStack的自动化安装部署,目前已经到了OpenStack这一部分.自动化部署首 ...
- IE浏览器部分版本不支持background-size属性问题
background-size是CSS3新增的属性,但是IE8以下还是不支持,可以通过滤镜来实现这样的一个效果 background-size:contain; // 缩小图片来适应元素的尺寸(保持像 ...
- attribute constructor&destructor
attribute constructor&destructor 在看openwrt里libnl-tiny这个库的时候,遇到了C里面的构造函数这个概念. static void __init ...
- HDOJ1002
#include <iostream>#include<stdio.h> using namespace std;int main(){ int T, count_T; cha ...
- 2016/06/13 phpexcel 未完待续
①准备工作: 1,php版本不能太低 2,去官网下载PHPExcel插件 http://phpexcel.codeplex.com/ 3,解压后提取classes文件夹到工作目录,并重命名为PH ...
- HDU 6183 Color it cdq分治 + 线段树 + 状态压缩
Color it Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others) Pro ...
- 用Qt编写的计算文件MD5值的Demo
Dialog.ui <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0& ...
- ZeroMQ 初步认识
http://www.danieleteti.it/zeromq-for-delphi/ https://my.oschina.net/zeroflamy/blog/109457 http://zer ...
- (深入理解计算机系统) bss段,data段、text段、堆(heap)和栈(stack)
bss段: bss段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域. bss是英文Block Started by Symbol的简称. bss段属于静态内存分配. ...