有向图的强联通分量 Tarjan算法模板
//白书 321页 #include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<stack> using namespace std; const int maxn=5003; vector<int>g[maxn];//g保存原始图 int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt; //pre[u]为节点u的搜索次序编号;lowlink[u]为u或u的子树能够追溯到的最早的栈中结点的编号 //sccno[i]为i所在的scc的编号;scc_cnt为scc计数器 stack<int>s;//保存当前scc中的节点 void dfs(int u) { pre[u]=lowlink[u]=++dfs_clock;//设置节点u次序编号lowlink初值 s.push(u); for(int i=0;i<g[u].size();i++){ int v=g[u][i]; if(!pre[v]){ //如果v没有被访问过 dfs(v); //继续向下找 lowlink[u]=min(lowlink[u],lowlink[v]); } else if(!sccno[v])//如果节点v还在栈内 lowlink[u]=min(lowlink[u],pre[v]); } if(lowlink[u]==pre[u]){ //如果节点u是强连通分量的根 scc_cnt++; for(;;){ int x=s.top();//x退栈为该强连通分量中的一个点 s.pop(); sccno[x]=scc_cnt; if(x==u) break; } } } void find_scc(int n) { dfs_clock=scc_cnt=0; memset(pre,0,sizeof(pre)); memset(sccno,0,sizeof(sccno)); for(int i=0;i<n;i++) if(!pre[i]) dfs(i); } int main() { return 0; }