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
冥冥之中觉得见过这个题.也就只是见过…
这题就是求缩点后出读为0的强联通分量,并且陈组成这个强联通分量里的点输出出来.
代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <stack>
#include <cstring>
#define mem(a,b) memset(a,b,sizeof(a))
#define maxn int(1e6+100)
using namespace std;
stack<int>st;
int cnt, k, m, n, cntt;
int dfn[maxn], low[maxn], head[maxn], vis[maxn], id[maxn], out[maxn], ans[maxn];
struct node {
int v, next, w;
} edge[maxn];
void addedge(int u, int v) {
edge[++cntt].v = v;
edge[cntt].next = head[u];
head[u] = cntt;
}
void tarjan(int u) {
dfn[u] = low[u] = ++k;
st.push(u);
vis[u] = 1;
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].v;
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if (vis[u]) {
low[u] = min(low[u], dfn[v]);
}
}
if (low[u] == dfn[u]) {
cnt++; int v;
do {
v = st.top();
st.pop();
vis[v] = 0;
id[v] = cnt;
} while (u != v);
}
}
int main() {
int x, y;
while (scanf("%d", &n) != EOF && n) {
memset(head, 0, sizeof head); cntt = cnt = k = 0;
memset(low, 0, sizeof low);
memset(dfn, 0, sizeof dfn);
memset(ans, 0, sizeof ans);
memset(id, 0, sizeof id);
memset(out, 0, sizeof out);
memset(vis, 0, sizeof vis);
scanf("%d", &m); int tot = 0;
for (int i = 0; i < m; i++) {
scanf("%d%d", &x, &y);
addedge(x, y);
}
for (int i = 1; i <= n; i++) {
if (!dfn[i]) {
tarjan(i);
}
}
for (int i = 1; i <= n; i++) {
for (int j = head[i]; j; j = edge[j].next) {
int u = i, v = edge[j].v;
if (id[u] != id[v]) {
out[id[u]]++;
}
}
}
for (int i = 1; i <= cnt; i++) {
if (out[i] > 0) continue;
for (int j = 1; j <= n; j++)
if (id[j] == i)
ans[++tot] = j;
}
sort(ans + 1, ans + tot + 1);
for (int i = 1; i <= tot; i++)
if (i == tot) cout << ans[i] << endl;
else cout << ans[i] << " ";
}
return 0;
}