强连通~~

题目大意:给一个有向图,问该图是否满足以下两个条件:1.它是一个强连通图。2.它的每一条边仅属于一个环。如果满足输出YES,否则输出NO

思路:刚开始想着如果一个点产生两次松弛,则存在边属于至少两个环,结果发现因为有边已经入队列,不能完全的松弛。。。

再一想,如果一个点已经入队,又访问到该点并且该点不是一个根节点,则必会存在一条边至少属于两个环。

代码:

View Code
 1 # include<stdio.h>
2 # include<string.h>
3 # define N 20005
4 # define M 50005
5 # include<stack>
6 using namespace std;
7 struct node{
8 int from,to,next;
9 }edge[M];
10 int tol,head[N],dfn[N],low[N],flag,count,cnt,n;
11 bool visit[N],vis[N];
12 stack<int>S;
13 void add(int a,int b)
14 {
15 edge[tol].from=a;edge[tol].to=b;edge[tol].next=head[a];head[a]=tol++;
16 }
17 int min(int a,int b)
18 {
19 return a<b?a:b;
20 }
21 void tarjan(int u)
22 {
23 int j,v;
24 dfn[u]=low[u]=cnt++;
25 visit[u]=vis[u]=1;
26 S.push(u);
27 for(j=head[u];j!=-1;j=edge[j].next)
28 {
29 v=edge[j].to;
30 if(!visit[v])
31 {
32 tarjan(v);
33 low[u]=min(low[u],low[v]);
34 }
35 else if(vis[v])
36 {
37 low[u]=min(low[u],dfn[v]);
38 if(dfn[v]!=low[v]) flag=1;
39 }
40 if(flag) return;
41 }
42 if(dfn[u]==low[u])
43 {
44 count++;
45 do{
46 v=S.top();
47 S.pop();
48 vis[v]=0;
49 }while(v!=u);
50 }
51 }
52 int main()
53 {
54 int i,ncase,a,b;
55 scanf("%d",&ncase);
56 while(ncase--)
57 {
58 scanf("%d",&n);
59 tol=0;
60 memset(head,-1,sizeof(head));
61 while(scanf("%d%d",&a,&b)!=EOF)
62 {
63 if(!a && !b) break;
64 add(a,b);
65 }
66 memset(visit,0,sizeof(visit));
67 memset(vis,0,sizeof(vis));
68 flag=0;
69 count=0;
70 cnt=0;
71 for(i=0;i<n;i++)
72 if(!visit[i]) tarjan(i);
73 if(flag||count!=1) printf("NO\n");
74 else printf("YES\n");
75 }
76 return 0;
77 }
posted on 2011-08-04 10:19  奋斗青春  阅读(1415)  评论(2)    收藏  举报