#include<bits/stdc++.h>
using namespace std;
const int N=100000,M=200000;
//所有Tarjan都要:
// dfn[N],low[N],cnt=1,st,scc,zhan[N],top,前向星,vector<int>SCC[N]
//强连通 ,belong[N],inq[N]
//割边,边双 bridge[N], belong[N]
//点双,割点 cut[N],root
int dfn[N],low[N],cnt=1,zhan[N],top,st,belong[N],scc,head[N],root,n;
bool bridge[M],inq[N],cut[N];
vector <int>SCC[N];
struct bian
{
int nxt,to;
}b[M];
void add(int from,int to)
{
b[++cnt].nxt=head[from];
b[cnt].to=to;
head[from]=cnt;
}
void Tarjan1(int cur)//强连通
{
dfn[cur]=low[cur]=++st;
zhan[++top]=cur;inq[cur]=true;
int i=head[cur],v;
while(i!=0)
{
v=b[i].to;
if(dfn[v]==0)
{
Tarjan1(v);
low[cur]=min(low[cur],low[v]);
}
else
{
if(inq[v]==true)
{
low[cur]=min(low[cur],dfn[v]);
}
}
i=b[i].nxt;
}
if(low[cur]==dfn[cur])
{
scc++;
int ding;
do
{
ding=zhan[top];
inq[ding]=false;
zhan[top--]=0;
belong[ding]=scc;
SCC[scc].push_back(ding);
}while(ding!=cur);
}
}
void Tarjan2(int cur,int pre)//割边,边双
{
dfn[cur]=low[cur]=++st;
zhan[++top]=cur;
int i=head[cur],v;
while(i!=0)
{
v=b[i].to;
if(i!=pre)
{
if(dfn[v]==0)
{
Tarjan2(v,i^1);
low[cur]=min(low[cur],low[v]);
if(low[v]>dfn[cur])
{
bridge[i]=bridge[i^1]=true;
scc++;
int ding;
do
{
ding=zhan[top];
zhan[top--]=0;
belong[ding]=scc;
SCC[scc].push_back(ding);
}while(ding!=v);
}
}
else
low[cur]=min(low[cur],dfn[v]);
}
i=b[i].nxt;
}
}
void Tarjan3(int cur)
{
dfn[cur]=low[cur]=++st;
zhan[++top]=cur;
int i=head[cur],v,child=0;
while(i!=0)
{
v=b[i].to;
if(dfn[v]==0)
{
child++;
Tarjan3(v);
low[cur]=min(low[cur],low[v]);
if(low[v]>=dfn[cur])
{
if(root!=cur)
cut[cur]=true;
scc++;
int ding;
do
{
ding=zhan[top];
zhan[top--]=0;
SCC[scc].push_back(ding);
}while(ding!=v);
SCC[scc].push_back(cur);
}
}
else
low[cur]=min(low[cur],dfn[v]);
i=b[i].nxt;
}
if(cur==root&&child>=2)
{
cut[cur]=true;
}
}
int main()
{
for(int i=1;i<=n;i++)
{
if(dfn[i]==0)
Tarjan1(i);
if(dfn[i]==0)
{
Tarjan2(i,0);
int ding;
while(top>0)
{
ding=zhan[top];
zhan[top--]=0;
SCC[scc].push_back(ding);
}
}
if(dfn[i]==0)
root=i,Tarjan3(i);
}
return 0;
}

特殊点:
强连通的出栈在函数末,进入条件low[cur]=dfn[cur],break条件ding!=cur,注意要维护是否在栈中的数组inq,dfn[v]!=0且inq[v]==true时,才能进入else语句中更新low[cur];

边双和割边出栈在Tarjan过程中的dfn[v]=0中,判断是low[v]>dfn[cur],break条件ding!=v,结束后要清栈;

割点和点双联通在Tarjan过程中的dfn[v]=0中,判断是low[v]>=dfn[cur],break条件ding!=v,注意求割点时,若cur=root且child>=2,为割点;

最新文章

  1. day3 字典,集合,文件
  2. linux错误码
  3. 优化数据库的方法及SQL语句优化的原则
  4. JS案例之5——移动端触屏滑动
  5. zImage.img、ramdisk.img、system.img、userdata.img介绍及解包、打包方法
  6. hive与hbase集成
  7. linux/win7下安装websphere application server
  8. AngularJS自定义表单验证器
  9. linux-sfdisk 使用方法
  10. [转] iOS ABI Function Call Guide
  11. web从入门开始(3)-----第一个网页
  12. 发布支持多线程的PowerShell模块 &mdash;&mdash; MultiThreadTaskRunner
  13. 安装gcc提示no acceptable C compiler found in $PATH
  14. How to remotely shut down any PC on same network
  15. asp.net微软图表控件使用示例
  16. 阿里云全民云计算活动:云服务器ECS二折起(云主机)采购指南
  17. 项目构建工具Maven
  18. jsp的两种跳转方式和区别
  19. Spring Boot 集成 Redis 实现缓存机制
  20. 活字格Web应用平台学习笔记4 - 添加记录

热门文章

  1. Springboot+Dubbo使用Zipkin进行接口调用链路追踪
  2. Hadoop 3.1.1 - 概述 - 单节点安装
  3. linux下编译常见错误
  4. 痞子衡嵌入式:ARM Cortex-M内核那些事(9.1)- 存储保护(MPU - PMSAv6/7)
  5. Kubernetes安装报错总结
  6. 【python与机器学习实战】感知机和支持向量机学习笔记(一)
  7. elsa-core——1.Hello World:Console
  8. Java程序员的推荐阅读书籍
  9. elk 7.9.3 版本容器化部署
  10. SQL 练习29