浅谈Tarjan算法
Tarjan算法:
Tarjan算法是一种用于查找已知图中的强连通分量的方法(介绍似乎越来越草率了
时间复杂度:O(n+m)//n为点数,m为边数
算法思路:
1,首先对每个节点设置两个参数存储:dfn[i]表示第i个点被搜索到的次序编号(每个点的dfn值都不同,low[i]表示每个点在这棵树中的最小子树根(人话就是找爹;
2,对每个新节点,初始化零dfn[i]=low[i];
3,用栈作为容器存储新出现的节点,若这个点有出度,就依次遍历每个子节点,每次都更新最小值保证子树根最小;
4,若找到dfn[i]=low[i],则i为本强连通分量中的根节点,将i及比i后进栈的元素出栈,即为一个强连通分量;
5,应在循环中调用tarjan函数,使每个没被访问过的点都被访问到。
似乎没找到板子题那就自己创造板子吧。
似乎很简单不太用注释的样子。
#include<bits/stdc++.h> #define ri register int using namespace std; const int N=1e4; int n,m; int head[N],cnt; bool vis[N]; int dfn[N],low[N],tot; struct qwq{ int to,nxt; }e[N]; stack<int> s; void add(int u,int v){ e[++cnt].to=v; e[cnt].nxt=head[u]; head[u]=cnt; } void tarjan(int x){ dfn[x]=low[x]=++tot; s.push(x); vis[x]=1; for(ri i=head[x];i;i=e[i].nxt){ int v=e[i].to; if(!dfn[v]){ tarjan(v); low[x]=min(low[x],low[v]); } else if(vis[v]) low[x]=min(dfn[v],low[x]); } if(low[x]==dfn[x]){ for(;;){ int u=s.top(); s.pop(); printf("%d ",u); if(u==x) break; } putchar('\n'); } } int main(){ scanf("%d%d",&n,&m); int x,y; for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); add(x,y); } for(int i=1;i<=n;i++) if(!vis[i]) tarjan(i); return 0; }
浙公网安备 33010602011771号