学习目录:1.总结tarjian算法解决强连通分量问题的相关知识。
2.开始复习以前的知识。
一.tarjian算法解决强连通分量
如下图(来源于biibii邋遢大哥):
代码实现如下:
#include<bits/stdc++.h>
using namespace std;
struct Edge
{
int to,next;
}edge[500010];
int cnt,head[100010],dfn[100010],low[100010],book[100010],stackk[100010];//dfn[]:即时间戳,表示他在dfs(tarjan)中是第几个被搜到的,low[]表示该点通过有向边可回溯的最早的时间戳(dfn数组)
//链式前向星
void add(int a,int b)
{
cnt++;
edge[cnt].to=b;
edge[cnt].next=head[a];
head[a]=cnt;
}
int top,timee,ans;
void tarjan(int x)
{
timee++;
dfn[x]=low[x]=timee;
top++;
stackk[top]=x;
book[x]=1;//标记在栈中
for(int i=head[x];i!=-1;i=edge[i].next)
{
int y=edge[i].to;
if(dfn[y]==0)//该节点未被访问过
{
tarjan(y);
low[x]=min(low[y],low[x]);
}
else if(book[y]==1)
{
low[x]=min(low[y],dfn[x]);
}
}
if(low[x]==dfn[x])
{
ans++;//ans表示有几个强连通分量
while(stackk[top]!=x)
{
book[stackk[top]]=0;//标志其不在栈中
top--;
}
book[stackk[top]]=0;
top--;
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
head[i]=-1;
int x,y;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);//有一条从x到y的边
add(x,y);
}
for(int i=1;i<=n;i++)
if(dfn[i]==0)tarjan(i);
printf("%d",ans);
return 0;
}