#include <iostream> #include <cstring> #include <cstdlib> #include <vector> #include <cmath> #include <algorithm> #include <set> #include <queue> #include <string> #include <map> #include <stack> #define MAXN 1000004 #define MOD 1000000009 #define INF 0x7ffffff #define lowbit(x) (x)&(-x) using namespace std; int vis[MAXN]; //标记节点是否在栈中 int dfn[MAXN]; //记录走过每个节点时的时间戳 int low[MAXN]; //记录每个节点在各自的强连通分量中的最小时间戳 stack<int> sta; //存放一个强连通分量中的所有节点 int n,m; int cnt; //时间戳 int ans; vector<int> point[MAXN]; //邻接表 void init(){ memset(vis,0,sizeof(vis)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); for(int i=0;i<MAXN;++i){ point[i].clear(); } cnt = ans = 0; } void Tarjan(int u){ sta.push(u); vis[u] = 1; //标记在栈中 low[u] = dfn[u] = ++cnt; int len = point[u].size(); for(int i=0;i<len;++i){ int v = point[u][i]; if(!dfn[v]){ //如果没有走过 Tarjan(v); low[u] = min(low[v],low[u]); //如果可更新,那么更新每个节点的时间戳,此处是确认父子关系,即两个点已经是同一个强连通分量,但要比较父子关系 } else if(vis[v]){ low[u] = min(low[v],low[u]); //如果可更新,那么更新时间戳,此处是连接关系,相当于把一个点挂到对应的强连通份量上 } } if(low[u] == dfn[u]){ //找到一个强连通分量 cout << "Strongly connected components : "; while(!sta.empty()){ vis[sta.top()] = 0; cout << sta.top() << ' '; sta.pop(); } cout << endl; ++ans; } } void solve(){ for(int i=1;i<=n;++i){ if(!dfn[i]){ //如果i节点还没有走过,那么从i节点开始执行Tarjan算法 Tarjan(i); } } } int main(){ while(cin >> n >> m){ init(); int u,v; while(m--){ cin >> u >> v; point[u].push_back(v); } solve(); cout << "ans is " << ans << endl; } return 0; }
强连通分量Tarjan算法
最新推荐文章于 2023-06-05 21:27:11 发布