POJ 2553 The Bottom of a Graph

The Bottom of a Graph

Time Limit: 3000ms

Memory Limit: 65536KB

This problem will be judged on PKU. Original ID: 2553
64-bit integer IO format: %lld      Java class name: Main

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 vv 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, epairs 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

Source

Ulm Local 2003

解题:求这样的点,它能到的点,那点也可以到它,注意先后顺序。然后求强联通缩点,出度为0的集合,里面的点即为我们求得那些点

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <climits>
 7 #include <vector>
 8 #include <queue>
 9 #include <cstdlib>
10 #include <string>
11 #include <set>
12 #include <stack>
13 #define LL long long
14 #define pii pair<int,int>
15 #define INF 0x3f3f3f3f
16 using namespace std;
17 const int maxn = 6000;
18 struct arc {
19     int to,next;
20     arc(int x = 0,int y = -1) {
21         to = x;
22         next = y;
23     }
24 };
25 arc e[maxn*100];
26 int head[maxn],dfn[maxn],low[maxn],belong[maxn],my[maxn];
27 int tot,n,m,top,scc,idx,out[maxn],ans[maxn];
28 bool instack[maxn];
29 void init() {
30     for(int i = 0; i < maxn; ++i) {
31         dfn[i] = low[i] = belong[i] = 0;
32         instack[i] = false;
33         head[i] = -1;
34         out[i] = 0;
35     }
36     scc = tot = idx = top = 0;
37 }
38 void add(int u,int v){
39     e[tot] = arc(v,head[u]);
40     head[u] = tot++;
41 }
42 void tarjan(int u) {
43     dfn[u] = low[u] = ++idx;
44     my[top++] = u;
45     instack[u] = true;
46     for(int i = head[u]; ~i; i = e[i].next) {
47         if(!dfn[e[i].to]) {
48             tarjan(e[i].to);
49             low[u] = min(low[u],low[e[i].to]);
50         } else if(instack[e[i].to]) low[u] = min(low[u],dfn[e[i].to]);
51     }
52     if(dfn[u] == low[u]) {
53         scc++;
54         int v;
55         do {
56             v = my[--top];
57             instack[v] = false;
58             belong[v] = scc;
59         } while(v != u);
60     }
61 }
62 int main() {
63     int u,v;
64     while(~scanf("%d",&n)&&n) {
65         scanf("%d",&m);
66         init();
67         for(int i = 0; i < m; ++i) {
68             scanf("%d%d",&u,&v);
69             add(u,v);
70         }
71         for(int i = 1; i <= n; ++i)
72             if(!dfn[i]) tarjan(i);
73         for(int i = 1; i <= n; ++i)
74             for(int j = head[i]; ~j; j = e[j].next)
75                 if(belong[i] != belong[e[j].to]) out[belong[i]]++;
76         int cnt = 0;
77         for(int i = 1; i <= n; ++i)
78             if(!out[belong[i]]) ans[cnt++] = i;
79         if(cnt){
80             for(int i = 0; i < cnt; ++i)
81                 printf("%d%c",ans[i],i + 1 == cnt?‘\n‘:‘ ‘);
82         }else puts("");
83     }
84     return 0;
85 }

时间: 2024-08-07 08:36:38

POJ 2553 The Bottom of a Graph的相关文章

poj 2553 The Bottom of a Graph 【强连通图中出度为0点】

题目:poj 2553 The Bottom of a Graph 题意:大概题意是给出一个有向图,求强连通缩点以后出度为0的点. 分析:入门题目,先强连通缩点,然后表示出度为0的,枚举输出即可. #include <cstdio> #include <vector> #include <iostream> #include <stack> #include <cstring> using namespace std; const int N =

POJ 2553 The Bottom of a Graph(Tarjan,强连通分量)

解题思路: 本题要求 求出所有满足"自己可达的顶点都能到达自己"的顶点个数,并从小到大输出. 利用Tarjan算法求出强连通分量,统计每个强连通分量的出度,出度为0的强连通分量内的顶点即为所求顶点. #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <cmath

POJ 2553 The Bottom of a Graph TarJan算法题解

本题分两步: 1 使用Tarjan算法求所有最大子强连通图,并且标志出来 2 然后遍历这些节点看是否有出射的边,没有的顶点所在的子强连通图的所有点,都是解集. Tarjan算法就是模板算法了. 这里使用一个数组和一个标识号,就可以记录这个顶点是属于哪个子强连通图的了. 然后使用DFS递归搜索所有点及其边,如果有边的另一个顶点不属于本子强连通图,那么就说明有出射的边. 有难度的题目: #include <stdio.h> #include <stdlib.h> #include &l

POJ 2553 The Bottom of a Graph(强连通分量)

POJ 2553 The Bottom of a Graph 题目链接 题意:给定一个有向图,求出度为0的强连通分量 思路:缩点搞就可以 代码: #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <stack> using namespace std; const int N = 5005; int n, m; vector&l

[tarjan] poj 2553 The Bottom of a Graph

题目链接: http://poj.org/problem?id=2553 The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 8899   Accepted: 3686 Description We will use the following (standard) definitions from graph theory. Let V be a nonempty and fini

poj 2553 The Bottom of a Graph【强连通分量求汇点个数】

The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 9641   Accepted: 4008 Description We will use the following (standard) definitions from graph theory. Let V be a nonempty and finite set, its elements being called ver

POJ 2553 The Bottom of a Graph (强连通分量)

题目地址:POJ 2553 题目意思不好理解.题意是:G图中从v可达的全部点w,也都能够达到v,这种v称为sink.然后升序输出全部的sink. 对于一个强连通分量来说,全部的点都符合这一条件,可是假设这个分量还连接其它分量的话,则肯定都不是sink.所以仅仅须要找出度为0的强连通分量就可以. 代码例如以下: #include <iostream> #include <string.h> #include <math.h> #include <queue>

POJ 2553 The Bottom of a Graph 【scc tarjan】

图论之强连通复习开始- - 题目大意:给你一个有向图,要你求出这样的点集:从这个点出发能到达的点,一定能回到这个点 思路:强连通分量里的显然都可以互相到达 那就一起考虑,缩点后如果一个点有出边,一定不在点集内,因为缩点后是DAG,无环,因此一定不能回到原来的点,所以找到出度为0的点即可 #include<cstdio> #include<string.h> #include<math.h> #include<algorithm> #include<io

POJ 2553 The Bottom of 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×V, its elements being called edges. Then G