强连通分量 ZQUOJ 21467&&POJ 2553 The Bottom of a Graph

Description

We will use the following (standard) definitions from graph theory. Let V be a nonempty and finite set, its elements being called vertices (or nodes). Let E be a subset of the Cartesian product V x V, its elements being called edges. Then G=(V,E) is called a directed graph. 
Let n be a positive integer, and let p=(e, ... , e) be a sequence of length n of edges ei  E such that ei = (vi ,vi+1 ) for a sequence of vertices ( v,... , vn+1 ). Then p is called a path from vertex v1 to vertex vn+1 in G and we say that vn+1 is reachable from v1, writing ( v vn+1 )
Here are some new definitions. A node v in a graph G=( V, E ) is called a sink, if for every node w in G that is reachable from vv is also reachable from w. The bottom of a graph is the subset of all nodes that are sinks, i.e., bottom(G) = { vV | w∈V: (vw)  (wv) }. You have to calculate the bottom of certain graphs.

Input

The input contains several test cases, each of which corresponds to a directed graph G. Each test case starts with an integer number v, denoting the number of vertices of G=( V, E ), where the vertices will be identified by the integer numbers in the set V={ 1 , ... , v }. You may assume that 1 <= v <= 5000. That is followed by a non-negative integer e and, thereafter,e pairs of vertex identifiers v, w, ... , v, we with the meaning that (vi , wi   E. There are no edges other than specified by these pairs. The last test case is followed by a zero.

Output

For each test case output the bottom of the specified graph on a single line. To this end, print the numbers of all nodes that are sinks in sorted order separated by a single space character. If the bottom is empty, print an empty line.

Sample Input

3 3
1 3 2 3 3 1
2 1
1 2
0

Sample Output

1 3
2

题目大意,给定一个有向图,按顺序输出“自己可达的顶点都可到达自己”的顶点。

解题思路:先求出图的强连通分量,缩点,求出度为0的强连通分量中的顶点,并按按顺序输出。

有关强强连通分量的算法请参考:http://www.byvoid.com/blog/scc-tarjan/(Tarjan算法)

                                          http://www.cnblogs.com/luweiseu/archive/2012/07/14/2591370.html(Tarjan,Kosaraju,Garbow)

                                          http://blog.csdn.net/liguanxing/article/details/5665520(Kosaraju算法)

                                          http://hi.baidu.com/yy17yy/item/8f4142dee291e6ee3cc2cb2f(Garbow算法)

 

AC代码(Tarjan):

View Code
 1 #include<stdio.h>
 2 #include<string.h>
 3 typedef struct
 4 {
 5     int v,next;
 6 }Node;
 7 Node e[50000];
 8 int n,m,index,top,count;
 9 int first[5001],DFN[5001],Low[5001],ver[5001];
10 int belong[5001],stack[5001],instack[5001],val[5001],degree[5001];
11 void Tarjan(int i)
12 {
13     int k,j,v;
14     DFN[i]=Low[i]=index++;
15     instack[i]=true;
16     stack[top++]=i;
17     for(j=first[i];j!=-1;j=e[j].next)
18     {
19         k=e[j].v;
20         if(!DFN[k])
21         {
22             Tarjan(k);
23             if(Low[k]<Low[i])
24                 Low[i]=Low[k];
25         }
26         else if(instack[k]&&DFN[k]<Low[i])
27             Low[i]=DFN[k];
28     }
29     if(Low[i]==DFN[i])
30     {
31         count++;
32         do{
33             v=stack[--top];
34             instack[v]=false;
35             belong[v]=count;
36             val[count]++;
37         }while(i!=v);
38     }
39 }
40 int main()
41 {
42     int g,i,j,u,v;
43     while(scanf("%d",&n)&&n)
44     {
45         scanf("%d",&m);
46         g=0; index=0; top=0; count=0;
47         memset(first,-1,sizeof(first));
48         memset(DFN,0,sizeof(DFN));
49         memset(Low,0,sizeof(Low));
50         memset(degree,0,sizeof(degree));
51         for(i=0;i<m;i++)
52         {
53             scanf("%d%d",&u,&v);
54             e[g].v=v;
55             e[g].next=first[u];
56             first[u]=g++;
57         }
58         for(i=1;i<=n;i++)
59             if(!DFN[i])
60                 Tarjan(i);
61         for(i=1;i<=n;i++)
62             for(j=first[i];j!=-1;j=e[j].next)
63             {
64                 v=e[j].v;
65                 if(belong[i]!=belong[v])
66                     degree[belong[i]]++;
67             }
68         for(i=1;i<=n;i++)
69         {
70             if(!degree[belong[i]])
71                 printf("%d ",i);
72         }
73         printf("\n");
74     }
75     return 0;
76 }

AC代码(Kosaraju):

View Code
 1 #include<stdio.h>
 2 #include<string.h>
 3 typedef struct
 4 {
 5     int u,v,next1,next2;
 6 }Node;
 7 Node e[50000];
 8 int n,m,index;
 9 int first1[5001],first2[5001],vis[5001],belong[5001],num[5001],degree[5001];
10 void dfs1(int i)
11 {
12     int j,k;
13     vis[i]=1;
14     for(j=first1[i];j!=-1;j=e[j].next1)
15     {
16         k=e[j].v;
17         if(!vis[k])
18             dfs1(k);
19     }
20     num[index++]=i;
21 }
22 void dfs2(int i)
23 {
24     int j,k;
25     vis[i]=1;
26     belong[i]=index;
27     for(j=first2[i];j!=-1;j=e[j].next2)
28     {
29         k=e[j].u;
30         if(!vis[k])
31             dfs2(k);
32     }
33 }
34 void kosaraju()
35 {
36     int i;
37     index=1;
38     memset(vis,0,sizeof(vis));
39     for(i=1;i<=n;i++)
40         if(!vis[i])
41             dfs1(i);
42     index=1;
43     memset(vis,0,sizeof(vis));
44     for(i=n;i>=1;i--)
45         if(!vis[num[i]])
46         {
47             dfs2(num[i]);
48             index++;
49         }
50 }
51 int main()
52 {
53     int g,i,j,u,v;
54     while(scanf("%d",&n)&&n)
55     {
56         g=0;
57         memset(first1,-1,sizeof(first1));
58         memset(first2,-1,sizeof(first2));
59         memset(degree,0,sizeof(degree));
60         scanf("%d",&m);
61         for(i=1;i<=m;i++)
62         {
63             scanf("%d%d",&u,&v);
64             e[g].v=v;
65             e[g].next1=first1[u];
66             first1[u]=g;
67             e[g].u=u;
68             e[g].next2=first2[v];
69             first2[v]=g++;
70         }
71         kosaraju();
72         for(i=1;i<=n;i++)
73             for(j=first1[i];j!=-1;j=e[j].next1)
74             {
75                 v=e[j].v;
76                 if(belong[i]!=belong[v])
77                     degree[belong[i]]++;
78             }
79         for(i=1;i<=n;i++)
80             if(!degree[belong[i]])
81                 printf("%d ",i);
82         printf("\n");
83     }
84     return 0;
85 }

 AC代码(Garbow):

View Code
 1 #include<stdio.h>
 2 #include<string.h>
 3 typedef struct
 4 {
 5     int v,next;
 6 }Node;
 7 Node e[50000];
 8 int n,m,index,top1,top2,count;
 9 int first[5001],low[5001],stack1[5001],stack2[5001];
10 int belong[5001],degree[5001];
11 void Garbow(int i)
12 {
13     int j,k;
14     stack1[++top1]=stack2[++top2]=i;
15     low[i]=index++;
16     for(j=first[i];j!=-1;j=e[j].next)
17     {
18         k=e[j].v;
19         if(!low[k])
20             Garbow(k);
21         else if(!belong[k])
22         {
23             while(low[stack2[top2]]>low[k])
24                 top2--;
25         }
26     }
27     if(stack2[top2]==i)
28     {
29         top2--;
30         count++;
31         do{
32             k=stack1[top1--];
33             belong[k]=count;
34         }while(k!=i);
35     }
36 }
37 int main()
38 {
39     int g,i,j,u,v;
40     while(scanf("%d",&n)&&n)
41     {
42         scanf("%d",&m);
43         g=0; top1=top2=-1; index=1; count=0;
44         memset(first,-1,sizeof(first));
45         memset(low,0,sizeof(low));
46         memset(belong,0,sizeof(belong));
47         memset(degree,0,sizeof(degree));
48         for(i=1;i<=m;i++)
49         {
50             scanf("%d%d",&u,&v);
51             e[g].v=v;
52             e[g].next=first[u];
53             first[u]=g++;
54         }
55         for(i=1;i<=n;i++)
56             if(!low[i])
57                 Garbow(i);
58         for(i=1;i<=n;i++)
59             for(j=first[i];j!=-1;j=e[j].next)
60             {
61                 v=e[j].v;
62                 if(belong[i]!=belong[v])
63                     degree[belong[i]]++;
64             }
65         for(i=1;i<=n;i++)
66             if(!degree[belong[i]])
67                 printf("%d ",i);
68         printf("\n");
69     }
70     return 0;
71 }

 

原文地址:https://www.cnblogs.com/frog112111/p/2626935.html