Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1907 Accepted Submission(s): 879
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<stack> using namespace std; const int maxn=20004; int t,n,flag; vector<int>g[maxn];//g保存原始图 int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt,vis[maxn]; //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); int sum=0; for(int i=0;i<(int)g[u].size();i++){ int v=g[u][i]; if(vis[v]) {flag=false;return;}//性质1 if(!pre[v]){ dfs(v); lowlink[u]=min(lowlink[u],lowlink[v]); if(lowlink[v]>pre[u]) {flag=false;return;}//性质2 if(lowlink[v]<pre[u]) sum++;//性质3 if(sum>1) {flag=false;return;} } else if(!sccno[v]){ lowlink[u]=min(lowlink[u],pre[v]); sum++;//性质3 if(sum>1) {flag=false;return;} } } if(lowlink[u]==pre[u]){ //如果节点u是强连通分量的根 scc_cnt++; for(;;){ int x=s.top();//x退栈为该强连通分量中的一个点 s.pop(); sccno[x]=scc_cnt; if(x==u) break; } } vis[u]=true; } void find_scc() { dfs_clock=scc_cnt=0; flag=true; memset(pre,0,sizeof(pre)); memset(sccno,0,sizeof(sccno)); memset(vis,false,sizeof(vis)); for(int i=0;i<n;i++) if(!pre[i]) dfs(i); } int main() { scanf("%d",&t); while(t--){ scanf("%d",&n); int a,b; for(int i=0;i<=n;i++) g[i].clear();//记住向量清空 while(scanf("%d%d",&a,&b)){ if(a==0&&b==0) break; g[a].push_back(b); } find_scc(); if(flag) cout<<"YES\n"; else cout<<"NO\n"; } return 0; }
原文:http://www.cnblogs.com/--ZHIYUAN/p/6357982.html