Calculate the number of key vertex of a non-loop directed graph. (I have just passed cet6 recently. Yeah, 1y. Show off ~~~~~)
What is key vertex? It is to remove the point from the start point to the end point. Is there a difference with the cut point? Here is the key.
At first glance, it is the graph theory of "beep --", which may be related to the minimum cut, but cannot be constructed. Alas, the network stream is unfamiliar.
But you can still do it after thinking about it. You can find a path from the start point to the end point, and the key will all be on this path (if there is no path, it will all be counted as the key ).
Then start searching, but the first vertex in the path will not be searched down from this vertex. If we can still find the vertex after the first vertex, then this vertex will not be the key. Otherwise, it is the key.
Specific Practices:
Initialization:
First, the vertex on the path starts from 0. vertices not on the path are marked as-1. Record the edge corresponding to the label.
Set the limit to 1 (because we need to determine whether the 1st points in the path are keys, so we should not search for the 1st points. 0 and the last vertex must be the key, so the limit starts from 1) and puts the first edge starting from the start point into the queue.
Start:
An edge is taken out of the queue, and the next edge is put into the queue (I saved it in a forward table ).
There are three conditions for the points obtained by this edge: (of course, the points searched will not be searched again)
1. If the number is smaller than limit, you can continue searching and put the first edge starting from this vertex into the queue.
2. The label is equal to limit. Do nothing.
3. If the number is greater than limit, it indicates that none of the above labels are keys (except for keys found ), set limit as the current label (because we need to check whether this point is a key, and we don't need to worry about it ), at the same time, don't forget to put the first edge of the previous limit point in the queue (because it was not put in 2nd cases ).
If the number is the last vertex in the path, break the key. You do not need to determine the key.
If the queue is empty, the point corresponding to the current limit is the key. Well, now we need to determine the next vertex. Then, the edge starting from this vertex will be added, and result ++, limit ++. Of course, when the limit corresponds to the end of the path, the break is okay.
Finally, the result is followed by 2 at the beginning and end.
It is O (e) complexity that only scans each side once. It ran more than 1000 ms.
After reading discuss, it would take 1 s for the input, and those running within 1 s must have used the input plug-in. It would be easy to get started, hey, hey ~~~~~~~~
# Include <iostream >#include <queue> # define INF 2100000000 using namespace STD; struct edge {int U, V, next ;}; edge [300000]; int head [100000], en; bool mark [100000]; int n, m, S, E; int f_min (int x, int y) {return x <Y? X: Y;} void insert (int u, int v) {edge [En]. U = u; edge [En]. V = V; edge [En]. next = head [u]; head [u] = EN ++;} int scan () {int res = 0, ch; while (! (CH = getchar ()> = '0' & Ch <= '9'); Res = CH-'0 '; while (CH = getchar ()> = '0' & Ch <= '9') RES = res * 10 + (CH-'0 '); return res;} bool get_in () {If (scanf ("% d", & N, & M) = EOF) return 0; memset (Head,-1, sizeof (head); en = 0; int U, V; while (M --) {u = scan (); V = scan (); insert (u, v);} scanf ("% d", & S, & E); return 1;} int ID [100000], path [100000], PN; int cur [100000]; bool find_path () {path [0] = s; Pn = 1; Int I, e, U; for (I = 0; I <n; I ++) {cur [I] = head [I]; Mark [I] = 0 ;} mark [s] = 1; while (PN) {u = path [pn-1]; for (; cur [u]! =-1; cur [u] = edge [cur [u]. Next) {If (! Mark [edge [cur [u]. v]) break;} e = cur [u]; If (E =-1) {PN --; continue;} mark [edge [e]. v] = 1; path [pn ++] = edge [e]. v; If (edge [e]. V = e) break;} return PN> 0;} int que [300000], qhead, qtail; void limit_search () {int Lim = 1; int V, E, res = 2; for (INT I = 0; I <n; I ++) MARK [I] = 0; qhead = qtail = 0; que [qtail ++] = head [s]; Mark [s] = 1; while (lim <pn-1) {While (qtail> qhead) {e = que [qhead ++]; V = edge [e]. v; If (edge [e]. next! =-1) que [qtail ++] = edge [e]. next; If (MARK [v]) continue; Mark [v] = 1; if (ID [v] <Lim) {If (head [v]! =-1) que [qtail ++] = head [v];} else if (ID [v]> Lim) {If (head [path [Lim]! =-1) que [qtail ++] = head [path [Lim]; Lim = ID [v]; If (lim = pn-1) break ;}} if (lim = pn-1) break; If (head [path [Lim]! =-1) que [qtail ++] = head [path [Lim]; Res ++; Lim ++;} printf ("% d \ n ", res);} void run () {int I; for (I = 0; I <n; I ++) ID [I] =-1; if (! Find_path () {printf ("% d \ n", n); Return ;}for (I = 0; I <PN; I ++) id [path [I] = I; limit_search ();} int main () {While (get_in () Run (); Return 0 ;}