tarjan初学

来源:互联网 发布:java怎样输出数组 编辑:程序博客网 时间:2024/06/05 14:39

今天才开始学tarjan,感觉自己真的是太弱了。。。

tarjan所维护的各种可爱的东西:

DFN[i]:深度优先搜索遍历时节点i被搜索的次序。
low[i]:节点i能够回溯到的最早位于栈中的节点。

身为蒟蒻的我现在只会求一个图的强连通分量有几个~~~~(>_<)~~~~

当LOW【x】=DFN【x】时说明我们找到了一个,于是开始退栈,退到x从栈中出来为止。

题目:https://www.luogu.org/problem/show?pid=2863

题解:裸的求有多少个强联通分量,但是自己本身不算。

#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<cstdio>#include<cmath>using namespace std;bool visit[500005];int low[500005];int dfn[500005];int head[500005];int s[500005];struct Eage{int next;int to;}e[500005];int k=0;void add(int x,int y){k++;e[k].next=head[x];e[k].to=y;head[x]=k;}int ans=0,time1=0,top=0;void tarjan(int x){time1++;dfn[x]=time1; low[x]=time1;top++; s[top]=x; visit[x]=true;for (int i=head[x];i;i=e[i].next){int v=e[i].to;if (visit[v]) low[x]=min(low[x],low[v]);else if (!dfn[v]){tarjan(v);low[x]=min(low[x],low[v]);}}if(low[x]==dfn[x]){ans++; int sum=1;while (s[top]!=x){visit[s[top]]=false;top--;sum++;}top--; visit[x]=false;if (sum==1) ans--;}}int main(){int n,m;scanf("%d%d",&n,&m);for (int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);add(x,y);}memset(dfn,0,sizeof(dfn));memset(visit,false,sizeof(visit)); for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);printf("%d",ans);return 0;}