1. 程式人生 > >tarjan求強連通分量+縮點+割點以及一些證明

tarjan求強連通分量+縮點+割點以及一些證明

#include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int dfn[10010],low[10010],vis[10010],stack[10010],color[10010],du[10010],cnt[10010]; int n,m,top,sum,deep,tmp,ans; vector<int> g[10010]; void tarjan(int
u) { dfn[u]=low[u]=++deep; vis[u]=1; stack[++top]=u; int sz=g[u].size(); for(int i=0; i<sz; 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],low[v]); } } } if(dfn[u]==low[u]) { color[u]=++sum; vis[u]=0; while(stack[top]!=u) { color[stack[top]]=sum; vis[color[top--]]=0; } top--; } } int main() { while(scanf("%d%d",&n,&m)!=EOF) { memset(vis,
0,sizeof(du)); memset(vis,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); memset(vis,0,sizeof(vis)); memset(vis,0,sizeof(cnt)); memset(vis,0,sizeof(color)); memset(vis,0,sizeof(stack)); for(int i=1; i<=n; i++) { g[i].clear(); } for(int i=1; i<=m; i++) { int from,to; scanf("%d%d",&from,&to); g[from].push_back(to); } for(int i=1; i<=n; i++) { if(!dfn[i]) { tarjan(i); } } for(int i=1; i<=n; i++) { int sz=g[i].size(); for(int j=0; j<sz; j++) { int v=g[i][j]; if(color[v]!=color[i]) { du[color[i]]++; } } cnt[color[i]]++; } for(int i=1; i<=sum; i++) { if(du[i]==0) { tmp++; ans=cnt[i]; } } if(tmp==0) { printf("0\n"); } else { if(tmp>1) { printf("0\n"); } else { printf("%d\n",ans); } } } }