传送门: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