传送门:Cactus
判断给定的有向图是否满足 1.强连通 2 每一条边属于且仅属于一个环?YES:NO
存在有两种情况(yy一下)
1.他的子节点在栈中
2.他的子节点的最早的时间戳不是他
#include <stdio.h> #include <string.h> #include <vector> #include <stack> #include <algorithm> using namespace std; #define N 20005 stack<int>sta; vector<int>mp[N]; int dfn[N]; int low[N]; int InStack[N]; int indexx,number; int n, m; int id[N]; int cnt[N]; int flag ; void tarjan(int u) { InStack[u] = 1; low[u] = dfn[u] = ++ indexx; sta.push(u); for (int i = 0; i < mp[u].size(); ++ i) { int t = mp[u][i]; if (dfn[t] == 0) { tarjan(t); if(dfn[u]!=low[t]) cnt[u]++ ;//在如果t的祖先不是u的话,肯定要加一个环的, low[u] = min(low[u], low[t]); } else if (InStack[t] == 1) { cnt[u]++;//想了一下在这不用加判断的,因为既然在这访问到了,说明他肯定存在一个环 low[u] = min(low[u], dfn[t]); } if(cnt[u]>1) flag =1; } if (low[u] == dfn[u]) { ++ number; while (!sta.empty()) { int v = sta.top(); sta.pop(); id[v]=number; InStack[v] = 0; if (v == u) break; } } } int main() { int T; scanf("%d",&T); while(T--){ flag =0; memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(InStack, 0, sizeof(InStack)); memset(cnt,0,sizeof(cnt)); indexx = number = 0; scanf("%d",&n); for (int i = 1; i <= n; ++ i) { mp[i].clear(); } while(!sta.empty()) sta.pop(); int a,b; while(scanf("%d%d",&a,&b),a+b) { mp[a+1].push_back(b+1); } for(int i=1; i<=n; i++) if(!dfn[i]) tarjan(i); if(number>1) { printf("NO\n"); continue; } else { if(flag) puts("NO"); else puts("YES"); } } }
原文地址:http://blog.csdn.net/u013076044/article/details/41729625