The Bottom of a Graph
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 11632 | Accepted: 4788 |
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.
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
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
#define mms(x) memset(x, 0, sizeof x)
#define MAX 1000000
vector<int > v[MAX];
int dfn[MAX], low[MAX], Stack[MAX], col[MAX], vis[MAX], out[MAX],ans[MAX];
int n, m, sig, pos, num, t;
void init()
{
mms(out);
mms(dfn);
mms(low);
mms(vis);
mms(Stack);
mms(col);
mms(ans);
for(int i = 1; i <= n; i++)
v[i].clear();
num = 1, pos = -1, sig = 0, t = 0;
}
void Tarjan(int u)
{
vis[u] = 1;
low[u] = dfn[u] = num++;
Stack[++pos] = u;
for(int i = 0; i < v[u].size(); i++)
{
int uv = v[u][i];
if(vis[uv] == 0)
Tarjan(uv);
if(vis[uv] == 1)
low[u] = min(low[u], low[uv]);
}
if(dfn[u] == low[u])
{
sig++;
do
{
col[Stack[pos]] = sig;
vis[Stack[pos]] = -1;
}
while(Stack[pos--] != u);
}
}
void Slove()
{
for(int i = 1; i <= n; i++)
if(vis[i] == 0)
Tarjan(i);
for(int i = 1; i <= n; i++)
for(int j = 0; j < v[i].size(); j++)
if(col[i] != col[v[i][j]])
out[col[i]]++;
for(int i = 1; i <= sig; i++)
if(!out[i])
for(int j = 1; j <= n; j++)
if(col[j] == i)
ans[t++] = j;
sort(ans, ans + t);
for(int i = 0; i < t; i++)
if(i == t - 1)
cout << ans[i] << endl;
else
cout << ans[i] << " ";
}
int main()
{
ios::sync_with_stdio(false);
while(cin >> n && n)
{
init();
cin >> m;
for(int i = 0, x, y; i < m; i++)
{
cin >> x >> y;
v[x].push_back(y);
}
Slove();
}
return 0;
}