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

给一个有向图,我们用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. GitLab-CI部署及踩坑总结

    转载请注明出处:https://www.cnblogs.com/shining5/p/8863063.html 部署GitLab-CI 简介 GitLab_CI(gitlab continuous i ...

  2. Python——详解collections工具库

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天为大家介绍Python当中一个很好用也是很基础的工具库,叫做collections. collection在英文当中有容器的意思,所以顾 ...

  3. Java基础--冒泡排序算法

    冒泡排序算法的运作如下:(从后往前) 比较相邻的元素,如果第一个比第二个大,就交换他们两个. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的元素. 针对 ...

  4. AOP和spring AOP学习记录

    AOP基本概念的理解 面向切面AOP主要是在编译期或运行时,对程序进行织入,实现代理, 对原代码毫无侵入性,不破坏主要业务逻辑,减少程序的耦合度. 主要应用范围: 日志记录,性能统计,安全控制,事务处 ...

  5. 将url转化成file文件

            let img = "https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=508387608,28489740 ...

  6. 如何在Flutter中使用flutter_markdown

    很多博客,论坛都支持markdown语法,flutter也有支持markdown语法的插件flutter_markdown 安装依赖 dependencies: flutter: sdk: flutt ...

  7. ubuntu1804自带的vim和vi都是用什么版本?

    之前搜索vim一些命令时,经常看到有人说ubuntu自带的vim是是vim.tiny的,功能不全. 什么需要先卸载,再重装,真的是这样吗? 我查了一下,vim的版本号 vim --version vi ...

  8. 深入理解 vertical-align 属性

    语法 用来指定行内元素或表格元素的垂直对齐方式 相对父元素的值 baseline 使元素的基线与父元素的基线对齐.HTML规范没有详细说明部分可替换元素的基线,如textarea,这意味着这些元素使用 ...

  9. 通过实现简单聊天室了解websocket的基础使用

    websocket基础使用 用到的依赖包 websocket的依赖 <dependency> <groupId>javax.websocket</groupId> ...

  10. Kaggle 题目 nu-cs6220-assignment-1

    Kaggle题目 nu-cs6220-assignment-1 题目地址如下: https://www.kaggle.com/c/nu-cs6220-assignment-1/overview 这是个 ...