有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量(strongly connected components)。——百度百科
可以将tarjan想象为有向图中,图中各点互相可以联通的一种高级查并集。
通过tarjan可以将带有环的图缩减为无环图,从而简化题目的判断
DFN[x]:表示这个点x几次被遍历到;
LOW[x]:表示点x或点x的子树能够追溯到的最早的栈中节点的次序号;
int dfn[1000005],low[1000005],num=0,numb=0;
int bl[1000005];//记录i点属于哪个强连通分量
int nums[1000005];//记录第i个强连通分量有几个元素
stack<int>atack;
map<int,bool>vis;
void tarjan(int now)
{
dfn[now]=low[now]=++num;
atack.push(now);
vis[now]=true;
for(int i=0;i<v[now].size();i++)
{
int next=v[now][i];
if(dfn[next]==0)
{
tarjan(next);
low[now]=min(low[now],low[next]);
}
else if(vis[next]==1)
{
low[now]=min(low[now],dfn[next]);
}
}
if(dfn[now]==low[now])
{
numb++;
int q;
do
{
q=atack.top();
vis[q]=0;
atack.pop();
bl[q]=numb;
nums[numb]++;
}while(q!=now);
}
}