现在的位置: 首页 > 综合 > 正文

hdu 3594 (强连通)

2019年04月09日 ⁄ 综合 ⁄ 共 1076字 ⁄ 字号 评论关闭

题意:判断给定的有向图是否满足 1.强连通 2 每一条边属于且仅属于一个环

如果出现环,记录环上的每条边的out[]++

如果有out[]大于1的,说明有边出现在两个环上

 

 

 

 

 

 

 

#include<stdio.h>
#include<string.h>
#include<stack>
#include<vector>
using namespace std;
#define N 20010
vector<int>map[N];
int n,ok,dfn[N],fa[N],ins[N],low[N],out[N];
int ans,idx;
stack<int>Q;
void judge(int v,int u)
{

	while(u!=v)
	{
		out[u]++;
		if(out[u]>1){ok=0;return ;}
		u=fa[u];
	}
}
void Tarjan(int u)
{
	int v,j;
	dfn[u]=low[u]=idx++;
	Q.push(u);
	ins[u]=1;
	for(j=0;j<map[u].size();j++)
	{
		v=map[u][j];
		if(dfn[v]==-1)
		{
			fa[v]=u;
			Tarjan(v);
			low[u]=low[u]>low[v]?low[v]:low[u];
			
		}
		else if(ins[v]==1)
		{
			low[u]=low[u]>dfn[v]?dfn[v]:low[u];
			judge(v,u);//如果v已加入在Q,记录out[]的值
		}
		if(ok==0)
			return;
	}
	if(low[u]==dfn[u])
	{
		ans++;
		if(ans>1){ok=0;return ;}
		while(1)
		{
			v=Q.top();
			Q.pop();
			ins[v]=0;
			if(v==u)break;
		}
	}
}
int main()
{
	int i,j,t,x,y;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		while(scanf("%d%d",&x,&y),x+y!=0)
			map[x].push_back(y);
		memset(out,0,sizeof(out));
		memset(dfn,-1,sizeof(dfn));
		memset(ins,0,sizeof(ins));
		ans=idx=0;ok=1;
		for(i=0;i<n;i++)
		{
			if(dfn[i]==-1)
				Tarjan(i);
			if(ok==0)break;
		}
		if(ok==0)
			printf("NO\n");
		else printf("YES\n");
		for(i=0;i<n;i++)  
			map[i].clear(); 		
	}
	return 0;
}

 

 

抱歉!评论已关闭.