POJ 2553 The Bottom of a Graph Tarjan找环缩点(题解解释输入)

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×V, its elements being called edges. Then G=(V,E) is called a directed graph.
Let n be a positive integer, and let p=(e1,...,en) be a sequence of length n of edges ei∈E such that ei=(vi,vi+1) for a sequence of vertices (v1,...,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 (v1→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 v, v is also reachable from w. The bottom of a graph is the subset of all nodes that are sinks, i.e., bottom(G)={v∈V|∀w∈V:(v→w)⇒(w→v)}. 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 v1,w1,...,ve,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


定义:点v是汇点须满足 --- 对图中任意点u,若v可以到达u则必有u到v的路径;若v不可以到达u,则u到v的路径可有可无。
题意:在n个点m条边的有向图里面,问有多少个点是汇点。
解释一下输入:分别是V顶点数,E边数,下一行每两个点是一条边的出入点。

思路:很明显的Tarjan缩点,满足题意的汇点就是缩点以后出度为0的点。
 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxn = 5e3+5;
 5 int stack[maxn],dfn[maxn],low[maxn],head[maxn],dfs_num,top;
 6 int color[maxn],col_num,in[maxn],out[maxn],mm[maxn],a[maxn];
 7 bool vis[maxn];
 8 class edge
 9 {
10 public:
11     int to,next;
12 }e[maxn*maxn];
13 inline int gmin(int a,int b)
14 {
15     return a<b?a:b;
16 }
17 void Tarjan ( int x ) {
18          dfn[ x ] = ++dfs_num ;
19          low[ x ] = dfs_num ;
20          vis [ x ] = true ;//是否在栈中
21          stack [ ++top ] = x ;
22          for ( int i=head[ x ] ; i!=0 ; i=e[i].next ){
23                   int temp = e[ i ].to ;
24                   if ( !dfn[ temp ] ){
25                            Tarjan ( temp ) ;
26                            low[ x ] = gmin ( low[ x ] , low[ temp ] ) ;
27                  }
28                  else if ( vis[ temp ])low[ x ] = gmin ( low[ x ] , dfn[ temp ] ) ;
29          }
30          if ( dfn[ x ]==low[ x ] ) {//构成强连通分量
31                   vis[ x ] = false ;
32                   color[ x ] = ++col_num ;//染色
33                   while ( stack[ top ] != x ) {//清空
34                            color [stack[ top ]] = col_num ;
35                            vis [ stack[ top-- ] ] = false ;
36                  }
37                  top -- ;
38          }
39 }
40 
41 int main()
42 {
43     int n,m;
44     while(scanf("%d",&n)){
45     if(!n)break;
46     scanf("%d",&m);
47     col_num=dfs_num=top=0;
48     for(int i=1;i<=n;i++)
49         head[i]=in[i]=out[i]=dfn[i]=0;
50     for(int i=1;i<=m;i++)
51     {
52         int x,y;
53         scanf("%d%d",&x,&y);
54         e[i].next=head[x];
55         e[i].to=y;
56         head[x]=i;
57     }
58     for(int i=1;i<=n;i++)if(!dfn[i])Tarjan(i);
59     for(int i=1;i<=n;i++)
60     {
61         for(int j=head[i];j;j=e[j].next)
62         {
63             int t=e[j].to;
64             if(color[i]!=color[t])
65             {
66                 out[color[i]]++;
67                 in[color[t]]++;
68             }
69         }
70     }
71     int k=0,ans=0;
72     for(int i=1;i<=col_num;i++)
73         if(!out[i])mm[++k]=i;
74     for(int i=1;i<=k;i++)
75         for(int j=1;j<=n;j++)
76         if(mm[i]==color[j])a[++ans]=j;
77     sort(a+1,a+ans+1);
78     //printf("%d %d %d
",k,ans,col_num);忘记初始化 debug多组样例一直过不了而加的..
79     for(int i=1;i<=ans;i++)
80         printf("%d%c",a[i],i!=ans?' ':'
');
81     }
82     return 0;
83 }
View Code
 
原文地址:https://www.cnblogs.com/llllrj/p/9405932.html