算法思想: 首先要明确强连通图的概念,一个有向图中,任意两个点互相可以到达;什么是强连通分量?有向图的极大连通子图叫强连通分量。

给一个有向图,我们用Tarjan算法把这个图的子图(在这个子图内,任意两个点可以相互到达,极大的子图)缩成一个点,相当于化简;

怎样去做:从一个点开始遍历它能走到的下一个点(dfn记录时间戳,low记录能回到的最早的时间戳),每遍历到一个点,判断这个点如果没有走过(dfn值为零),继续深搜,如果走过了并且在栈里面说明可以形成一个环(那就可以缩成一个点,更新当前点low的值,回到更早的时间戳),搜完它可以到达所有的点以后回溯,更新low;直到回到 low[u]==dfn[u](环的“根节点"),出栈这个点上面的所有的点(包括这个点本身,他们可以缩成一个点).继续回溯.

特别注意:

        else if(instack[v])/*走过并且形成一个环??????*/
low[u]=min(low[u],dfn[v]);/*更新最小值low,合并集合*/
/*不能写成low[u]=min(low[v],low[u])*/

当计算有多少个强连通分量的时候,写成那个没关系,但是如果是求割点,两个语句求出来的low值不一样,值会偏小,割点判断错误(因为判断条件是if(low[v]>=dfn[u]))。

扩展:

计算出入度,问加多少条边可以变成一个整个连通分量:

在这里首先缩点,用一个color[ ]数组,将同一集合的点标记成某个序号(出栈的时候就是同一集合),最后遍历输入的边,用两个数组标记每一个集合的出度入度情况,得出入度和出度分别有几个集合为零,输出最大值。注意:调用tarjan函数的时候,用for循环,因为图可能不连通!还有当它本来就是一个连通分量的时候,特判一下。

例题:POJ 1236

Network of Schools

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
#define N 1010
vector<int>edge[N];
vector<int>belong[N];
stack<int>s;
int low[N];/*所属的强连通数组*/
int dfn[N];/*访问的顺序*/
bool instack[N];/*是否在栈内*/
int n,m,u,v,cnt,cntb;/*n个顶点,m条边*/
void Tarjan(int u)/*当前处于的节点*/
{
++cnt;/*计算访问到第几个点(时间戳)*/
dfn[u]=low[u]=cnt;/*访问的顺序(时间戳),low数组记录这个点所能回到的最早的时间戳*/
s.push(u);
instack[u]=true;
for(int i=0;i<edge[u].size();i++)/*下一个要走的节点*/
{
int v=edge[u][i];
if(!dfn[v])/*如果没走过*/
{
Tarjan(v);/*深搜*/
low[u]=min(low[u],low[v]);/*更新最小值low,合并集合*/
}
else if(instack[v])/*走过并且形成一个环??????*/
low[u]=min(low[u],dfn[v]);/*更新最小值low,合并集合*/
}
if(dfn[u]==low[u])/*回到环的起点,出栈*/
{
++cntb;
int node;
do
{
node=s.top();
s.pop();
instack[node]=false;
belong[cntb].push_back(node);/*将集合分组*/
}while(node!=u);
}
}
int main()
{
memset(instack,0,sizeof(instack));
cnt=0;cntb=0;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
edge[u].push_back(v);
}
Tarjan(1);/*从一号顶点开始遍历*/
for(int i=1;i<=n;i++)
printf("dfn:%d low:%d\n",dfn[i],low[i]);
for(int i=1;i<=cntb;i++)
{
printf("第%d组\n",i);
for(int j=0;j<belong[i].size();j++)
printf("%d ",belong[i][j]);
printf("\n");
}
return 0;
}
/*
7 11
1 2
2 3
2 5
2 4
3 5
3 7
7 5
5 6
6 7
4 1
4 5
*/

Tarjan算法(模板)的更多相关文章

  1. Tarjan 算法&模板

    Tarjan 算法 一.算法简介 Tarjan 算法一种由Robert Tarjan提出的求解有向图强连通分量的算法,它能做到线性时间的复杂度. 我们定义: 如果两个顶点可以相互通达,则称两个顶点强连 ...

  2. HDU 2586 ( LCA/tarjan算法模板)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:n个村庄构成一棵无根树,q次询问,求任意两个村庄之间的最短距离 思路:求出两个村庄的LCA,d ...

  3. tarjan算法模板

    终于能自己完整的打下来 #include<cstdio> #include<cstring> #include<iostream> #include<vect ...

  4. poj1236 Tarjan算法模板 详解

    思想: 做一遍DFS,用dfn[i]表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用low[i]表示i节点DFS过程中i的下方节点所能到达的开始时间最早的节点的开始时间.初始时dfn ...

  5. Tarjan算法模板(USACO03FALL受欢迎的牛)

    好文章 #include<bits/stdc++.h> using namespace std; const int N = 10010, M = 50010; int n, m; int ...

  6. 有向图的强联通分量 Tarjan算法模板

    //白书 321页 #include<iostream> #include<cstdio> #include<cstring> #include<vector ...

  7. 割点的tarjan算法模板

    基本思路: 朴素的思想是删除每一个点,然后去dfs,这样无疑会爆炸 换一种思路,怎样判断是割点呢,如果是根节点的话毫无疑问只要看子树的数目,但是如果不是根节点呢,不知大牛是怎样想到的 利用两个数组df ...

  8. POJ1236_A - Network of Schools _强连通分量::Tarjan算法

    Time Limit: 1000MS   Memory Limit: 10000K Description A number of schools are connected to a compute ...

  9. 一直想写的关于tarjan算法的理解——向struct edge大佬低头

    tarjan的算法精髓就是dfn[]和low[]数组 dfn[i]表示在该节点被搜索的次序(时间戳) low[i]表示i或i的子树可以追溯到的最早的栈中节点 判断有强连通分量的条件就是 dfn[i]= ...

随机推荐

  1. C++走向远洋——60(项目四、立体类族共有的抽象类)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  2. 54-with管理文件操作上下文

    目录 with管理文件操作上下文 with管理文件操作上下文 之前我们使用open()方法操作文件,但是open打开文件后我们还需要手动释放文件对操作系统的占用.其实我们可以更方便的打开文件,即Pyt ...

  3. zookeeper和dubbo安装与搭建(2)

    Zookeeper+Dubbo安装与搭建(2) (原创:黑小子-余) 一.环境配置:zookeeper3.6.0 + dubbo3.5.4 + maven3.6.1 + jdk1.8 + tomcat ...

  4. 续python学习(一)

    接上面没写完的知识点继写. 当然,这些知识点都很简单,可能没必要花费太多时间去记忆,多写写代码就会了. 5.字符串的使用.索引和切片是字符串主要的两个应用.索引:顾名思义就是找出某个字符在一个字符串中 ...

  5. 3DGIS+BIM集成与智慧城市应用

    ZTMap3D是基于网络的三维地理信息系统平台软件,利用 ZTMap3D能够实现三维地理信息和虚拟现实,是数字化地球和数字化城市建设的基础平台. BIM(building information mo ...

  6. 脚本写一行echo也能写出bug ? glob了解一下

    背景 最近处理一个 bug 很有意思,有客户反馈某个配置文件解析失败了,出错的那行的内容就只有一个字母 a. 最开始以为是谁改动了处理的脚本,但要到了问题代码中的脚本,比较发现跟库上是一样的. 又经过 ...

  7. css 一行自适应等比例布局

    一.浮动布局+百分比 .row { width:100%; overflow:hidden; zoom:1; } .item { float: left; width: 20%; } 该样式兼容性较好 ...

  8. Mathtype快捷键&小技巧

    Mathtype使用方便,能插入到Office等编辑器中,Latex公式在某些地方更加通用,如网页和书籍. 1. Mathtype简介 数学公式编辑器(MathType)是一款专业的数学公式编辑工具, ...

  9. C++ 函数模板/类模板

    #include <iostream> #include <vector> using namespace std; template < class T > // ...

  10. Codeforces Round #200 (Div. 2)E

    Read Time 题意:有一个数组,很多指针指在这个数组上,每次每个指针可以向左或向右移动一个位置.给出一些需要访问的位置,问访问用的最少时间. 一个指针只可能转一次方向.二分答案. #includ ...