Kosaraju算法
详见《挑战程序设计竞赛》p320
模板:
const int N=1e5+5; int n,m; vector<int>g[N]; vector<int>rg[N]; vector<int>vs; bool vis[N]; int cmp[N]; void add_edge(int u,int v) { g[u].pb(v); rg[v].pb(u); } void dfs(int u) { vis[u]=true; for(int i=0;i<g[u].size();i++) if(!vis[g[u][i]])dfs(g[u][i]); vs.pb(u); } void rdfs(int u,int k) { vis[u]=true; cmp[u]=k; for(int i=0;i<rg[u].size();i++) if(!vis[rg[u][i]])rdfs(rg[u][i],k); } int scc() { mem(vis,false); vs.clear(); for(int i=1;i<=n;i++)if(!vis[i])dfs(i); mem(vis,false); int k=0; for(int i=vs.size()-1;i>=0;i--)if(!vis[vs[i]])rdfs(vs[i],k++); return k; }
Tarjan算法模板:
const int N = 1e5 + 5; vector<int> g[N]; int low[N], dfn[N], stk[N], cmp[N], cnt = 0, top = 0, tot = 0; bool vis[N]; void tarjan(int u) { low[u] = dfn[u] = ++cnt; stk[++top] = u; vis[u] = true; //标记是否在栈中 for (int v : g[u]) { if(!dfn[v]) { tarjan(v); low[u] = min(low[u], low[v]); } else if(vis[v]) low[u] = min(low[u], dfn[v]); } if(low[u] == dfn[u]) { cmp[u] = ++tot; vis[u] = false; while(stk[top] != u) { cmp[stk[top]] = tot; vis[stk[top--]] = false; } top--; } }
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<vector> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=1e5+5; int n,m; vector<int>g[N]; vector<int>rg[N]; vector<int>vs; bool vis[N]; int cmp[N]; void add_edge(int u,int v) { g[u].pb(v); rg[v].pb(u); } void dfs(int u) { vis[u]=true; for(int i=0;i<g[u].size();i++) if(!vis[g[u][i]])dfs(g[u][i]); vs.pb(u); } void rdfs(int u,int k) { vis[u]=true; cmp[u]=k; for(int i=0;i<rg[u].size();i++) if(!vis[rg[u][i]])rdfs(rg[u][i],k); } int scc() { mem(vis,false); vs.clear(); for(int i=1;i<=n;i++)if(!vis[i])dfs(i); mem(vis,false); int k=0; for(int i=vs.size()-1;i>=0;i--)if(!vis[vs[i]])rdfs(vs[i],k++); return k; } int main() { ios::sync_with_stdio(false); cin.tie(0); cin>>n>>m; int u,v; for(int i=0;i<m;i++)cin>>u>>v,add_edge(u,v); int t=scc(); int ans=0; for(int i=1;i<=n;i++)if(cmp[i]==t-1)ans++,u=i; mem(vis,false); rdfs(u,0); for(int i=1;i<=n;i++)if(!vis[i])ans=0; cout<<ans<<endl; return 0; }