Question:
Calculate the strongly connected component with a degree of 0.
Ideas:
Point Reduction
There are two specific implementations:
1. traverse all edges. If the points at both ends of the edge are not in the same strongly connected component, the strong connected component of the starting point will be outdegree + 1.
# Include <cstdio> # include <cstring> # include <stack> # include <algorithm> using namespace std; // 0.03 s 4856 Kconst int MAXN = 5005; struct Pool {int pre, v;} p [MAXN * 100]; // enable int num, head [MAXN]; int low [MAXN]; int dfn [MAXN], index; int id [MAXN], size; bool vis [MAXN]; stack <int> s; int n, m; int deg [MAXN]; void clear () {num = 1; // calculate the adjacent edge, XOR or convenience. memset (head, 0, sizeof (head) starts from 2; memset (vis, false, sizeof (vis); memset (low, 0, s Izeof (low); memset (dfn, 0, sizeof (dfn); memset (deg, 0, sizeof (deg); Index = size = 0; while (! S. empty () s. pop ();} void add (int u, int v) {p [++ num]. v = v; p [num]. pre = head [u]; // The value of pre is 0, indicating that this edge is the first edge head [u] = num;} void Tarjan (int u) {dfn [u] = low [u] = ++ Index; s. push (u); vis [u] = true; for (int tmp = head [u], k; k = p [tmp]. v, tmp; tmp = p [tmp]. pre) {if (! Dfn [k]) {Tarjan (k); low [u] = min (low [u], low [k]);} else if (vis [k]) {low [u] = min (low [u], low [k]); // low [u] = min (low [u], dfn [k]); both of them are acceptable ~} If (dfn [u] = low [u]) {size ++; int k; do {k = s. top (); s. pop (); vis [k] = false; id [k] = size;} while (k! = U) ;}} void cal () {for (int I = 1; I <= n; I ++) {for (int tmp = head [I], k; k = p [tmp]. v, tmp; tmp = p [tmp]. pre) {if (id [I]! = Id [k]) {deg [id [I] ++ ;}}} int main () {while (scanf ("% d", & n ), n) {clear (); scanf ("% d", & m); for (int I = 0, u, v; I <m; I ++) {scanf ("% d", & u, & v); add (u, v) ;}for (int I = 1; I <= n; I ++) {if (! Dfn [I]) Tarjan (I);} cal (); bool blank = false; for (int I = 1; I <= n; I ++) {if (! Deg [id [I]) {if (! Blank) {printf ("% d", I); blank = true;} else printf ("% d", I );}} printf ("\ n ");}}
2. Mark the degree in the dfs process.
Set current node to u
If a black dot is accessed, the outbound value is not 0.
Normal if the gray point is accessed
If the white point is accessed, the white point k
If the searched component belongs to the same strongly connected component, low [k] <dfn [k] (Note that not necessarily low [k] <low [u], because k may be connected to a relatively low gray point, and u has been updated by a relatively high gray point ).
If the searched component belongs to another strongly connected component (different from u), it can be proved that low [k] = dfn [k], that is, k must be the entry.
The two in the bold Chinese characters include all non-zero outbound values, so as to achieve point reduction.
# Include <cstdio> # include <cstring> # include <stack> # include <algorithm> using namespace std; // 0.03 s 4812 Kconst int MAXN = 5005; struct Pool {int pre, v;} p [MAXN * 100]; // enable int num, head [MAXN]; int low [MAXN]; int dfn [MAXN], index; int id [MAXN], size; bool vis [MAXN]; stack <int> s; int n, m; bool black [MAXN]; bool odd [MAXN]; void clear () {num = 1; memset (head, 0, sizeof (head); memset (vis, false, sizeof (vis); memset (low, 0, sizeof (low); memset (dfn, 0, sizeof (dfn); memset (black, false, sizeof (black); memset (odd, false, sizeof (odd); Index = size = 0; while (! S. empty () s. pop ();} void add (int u, int v) {p [++ num]. v = v; p [num]. pre = head [u]; head [u] = num;} void Tarjan (int u) {dfn [u] = low [u] = ++ Index; s. push (u); vis [u] = true; for (int tmp = head [u], k; k = p [tmp]. v, tmp; tmp = p [tmp]. pre) {if (! Dfn [k]) {Tarjan (k); if (low [k] = dfn [k]) // if the white point is accessed, the new strongly connected component entry must be at this point black [u] = true; low [u] = min (low [u], low [k]);} else if (vis [k]) {low [u] = min (low [u], low [k]);} else black [u] = true ;} /// low only refers to the entry timestamp of the strongly connected component found. /// it is not the entry timestamp of the extremely large connected component. but it must be smaller than its own timestamp (that is, the entry point is equal ). if (dfn [u] = low [u]) {size ++; int k; do {k = s. top (); s. pop (); vis [k] = false; id [k] = size; if (black [k]) odd [size] = true;} while (K! = U) ;}} int main () {while (scanf ("% d", & n), n) {clear (); scanf ("% d ", & m); for (int I = 0, u, v; I <m; I ++) {scanf ("% d", & u, & v ); add (u, v) ;}for (int I = 1; I <= n; I ++) {if (! Dfn [I]) Tarjan (I);} bool blank = false; for (int I = 1; I <= n; I ++) {if (! Odd [id [I]) {if (! Blank) {printf ("% d", I); blank = true;} else printf ("% d", I );}} printf ("\ n ");}}