学习资料:https://www.cnblogs.com/shadowland/p/5872257.html
板子:
void tarjan(int u){ dfn[u]=low[u]=++cnt; sta[++top]=u; vis[u]=true; for(int i=0;i<g[u].size();i++){ int v=g[u][i]; if(!dfn[v]){ tarjan(v),low[u]=min(low[u],low[v]); } else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]){ cmp[u]=++tot; vis[u]=false; int len=top; while(sta[top]!=u){ cmp[sta[top]]=tot; vis[sta[top--]]=false; } top--; sum[tot]=len-top;//缩点,记录该联通块的大小 } }
例题:poj 2186 http://poj.org/problem?id=2186
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<vector> using namespace std; const int M=1e4+5; vector<int>g[M]; int out[M],cmp[M],dfn[M],low[M],sta[M],vis[M],sum[M],tot,cnt,top; void tarjan(int u){ dfn[u]=low[u]=++cnt; sta[++top]=u; vis[u]=true; for(int i=0;i<g[u].size();i++){ int v=g[u][i]; if(!dfn[v]){ tarjan(v),low[u]=min(low[u],low[v]); } else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]){ cmp[u]=++tot; vis[u]=false; int len=top; while(sta[top]!=u){ cmp[sta[top]]=tot; vis[sta[top--]]=false; } top--; sum[tot]=len-top; } } int main(){ int n,m; scanf("%d%d",&n,&m); while(m--){ int x,y; scanf("%d%d",&x,&y); g[x].push_back(y); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++){ for(int j=0;j<g[i].size();j++){ int v=g[i][j]; if(cmp[i]!=cmp[v]) out[cmp[i]]++; } } /*for(int i=1;i<=tot;i++) cout<<out[i]<<" "; cout<<endl;*/ int s=0; for(int i=1;i<=tot;i++){ if(!out[i]){ if(s){ return puts("0"),0; } else s=sum[i]; } } printf("%d\n",s); return 0; }
原文:https://www.cnblogs.com/starve/p/10946166.html