Idea: First scale down to a directed acyclic graph, it will inevitably contain a vertex with an outbound degree of 0/a vertex with an inbound degree of 0, because you need to add as many edges as possible, A maximum of N * (n-1) lines minus the original M edge. This is a strongly connected graph. The problem is to remove at least a few lines to make the graph less connected, in the original graph, if no degree is added, it is not connected, and the same is true if the degree of parallelism is 0. Therefore, find the point where the inbound/outbound degree is 0, KI (n-ki) is the smallest. Here, Ki is the number of vertices in the SCC after the contraction. The result is the smallest number of edges removed.
Clear thinking, 1a.
# Include <iostream> # include <vector> # include <cstdio> # include <cstring> # include <stack> using namespace STD; int n, m; const int maxv = 100030; vector <vector <int> edges (maxv); int visited [maxv]; int low [maxv]; int dfn [maxv]; int ind [maxv]; int outd [maxv]; int sccnum [maxv]; int SCC [maxv]; int num; int times; stack <int> S; int instack [maxv]; void Tarjan (int u) {LOW [u] = dfn [u] = times ++; instack [u] = 1; S. push (U); int Len = EDG Es [u]. size (); For (INT I = 0; I <Len; I ++) {int v = edges [u] [I]; if (visited [v] = 0) {visited [v] = 1; Tarjan (V); If (low [u]> low [v]) low [u] = low [v];} else if (instack [v] & low [u]> dfn [v]) {LOW [u] = dfn [v] ;}} if (dfn [u] = low [u]) // In an SCC {num ++; int temp; int snum = 0; do {snum ++; temp = S. top (); instack [temp] = 0; S. pop (); SCC [temp] = num;} while (temp! = U); sccnum [num] = snum ;}} void readin () // read data {scanf ("% d", & N, & M ); int A, B; For (INT I = 1; I <= m; I ++) {scanf ("% d", & A, & B ); edges [A]. push_back (B) ;}} void initialize () {num = times = 0; For (INT I = 0; I <= 100000; I ++) {dfn [I] = low [I] = ind [I] = outd [I] = visited [I] = sccnum [I] = SCC [I] = 0; edges [I]. clear () ;}} int solve () {for (INT I = 1; I <= N; I ++) if (visited [I] = 0) {visited [I] = 1; Tarjan (I) ;}if (num = 1) {return-1 ;}for (int I = 1; I <= N; I ++) {int Len = edges [I]. size (); For (Int J = 0; j <Len; j ++) {int v = edges [I] [J]; If (SCC [v]! = SCC [I]) {outd [SCC [I] ++; ind [SCC [v] ++ ;}} int mincut = 1000000000; for (INT I = 1; I <= num; I ++) {int temp = 0; if (outd [I] = 0 | ind [I] = 0) {temp = sccnum [I] * (N-sccnum [I]); if (temp <mincut) mincut = temp;} return N * (n-1)-m-mincut;} int main () {int t; CIN> T; INT cases = 1; while (t --) {initialize (); readin (); int ans = solve (); printf ("case % d: % d \ n ", cases ++, ANS);} return 0 ;}