Table of Contents

ExplanationImplementation

Explanation

Let's first compose the graph into many SCCs and construct the corresponding DAG with SCCs as vertices. The problem boils down to: How many edges will we need to add in the DAG such that the DAG becomes strongly connected?

From now on we will only consider the DAG. A node is a source if it has no incoming connections. On the other hand, a node is a sink if it has no outgoing connections. Let SS denote the set of sources and TT denote the set of sinks. We should only add edges that goes from a sink to a source (otherwise, any other edges that we add can be replaced with edges that goes from a sink to a source and connect more vertices).

For each vertex uSu \in S, we should find a unique vertex bTb \in T that it can reach. The sink it matches with can be arbitrary but it should only travel through vertices that have not been visited yet. Note that it may be the case that each source cannot be matched to a unique sink. For now, we've created many pairs (ui,vi)(u_i, v_i). With these pairs, one optimal construction is to add edges viui1v_i \rightarrow u_{i-1} for each i2i \geq 2 and v1ukv_1 \rightarrow u_k. This way, we create a "ring" where we can guarantee for all vertex that uiu_i, it can also reached by all vertices that is reachable from ui+1u_{i+1}. This is strongly connected because of the v1ukv_1 \rightarrow u_k edge. If we have a pair of vertices (a,b)(a, b) such that bb was reachable from aa but aa was not reachable from bb in the original graph, now we can start from bb and travel around the ring to aa.

However, there may be some sources and sinks that were not originally matched. We can connect each sink to a unique source with an edge so that their components are strongly connected. For any sources or sinks that still remain, we can just connect them to the new graph by adding an edge. Note that whether we connect a source or a sink to the main graph, the connection will propagate to the rest of the vertices in their SCCs.

Thus, the minimum number of edges we must add is max(S,T)\max(|S|,|T|). As an exercise, prove why it is optimal.

Implementation

Time Complexity: O(N+M)\mathcal{O}(N + M)

C++

#include <bits/stdc++.h>
using namespace std;
struct SCC {
vector<vector<int>> adj, c_adj, r_adj;
vector<int> c, v, ord;
SCC(vector<vector<int>> _adj) : adj(_adj) {}
void dfs(int i) {

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!