Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add document for scc #80

Merged
merged 2 commits into from
Mar 29, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions src/scc.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,88 @@
//! A `SccGraph` is a directed graph that calculates strongly connected components (SCC) in $O(|V| + |E|)$.

use crate::internal_scc;

/// A `SccGraph` is a directed graph that calculates strongly connected components (SCC) in $O(|V| + |E|)$.
TonalidadeHidrica marked this conversation as resolved.
Show resolved Hide resolved
///
/// # Example
///
/// ```
/// use ac_library_rs::SccGraph;
/// use proconio::{input, source::once::OnceSource};
///
/// input! {
/// from OnceSource::from(
/// "5\n\
/// 5\n\
/// 0 1\n\
/// 1 2\n\
/// 2 0\n\
/// 0 3\n\
/// 3 4\n",
/// ),
/// n: usize,
/// abs: [(usize, usize)],
/// }
///
/// let mut graph = SccGraph::new(n);
/// for (a, b) in abs {
/// graph.add_edge(a, b);
/// }
///
/// assert_eq!(graph.scc(), [&[0, 1, 2][..], &[3], &[4]]);
/// ```
pub struct SccGraph {
internal: internal_scc::SccGraph,
}

impl SccGraph {
/// Creates a new `SccGraph` with `n` edges.
///
/// # Constraints
///
/// - $0 \leq n \leq 10^8$
///
/// # Complexity
///
/// - $O(n)$
pub fn new(n: usize) -> Self {
SccGraph {
internal: internal_scc::SccGraph::new(n),
}
}

/// Adds a directed edge from the vertex `from` to the vertex `to`.
///
/// # Constraints
///
/// - $0 \leq$ `from` $< n$
/// - $0 \leq$ `to` $< n$
///
/// # Panics
///
/// Panics if the above constraints are not satisfied.
///
/// # Complexity
///
/// - $O(1)$ amortized
pub fn add_edge(&mut self, from: usize, to: usize) {
let n = self.internal.num_vertices();
assert!(from < n);
assert!(to < n);
self.internal.add_edge(from, to);
}

/// Calculates the strongly connected components (SCC) of directed graphs in $O(|V| + |E|)$.
///
/// Returns the list of the "list of the vertices" that satisfies the following.
///
/// - Each vertex is in exactly one "list of the vertices".
/// - Each "list of the vertices" corresponds to the vertex set of a strongly connected component. The order of the vertices in the list is undefined.
/// - The list of "list of the vertices" are sorted in topological order, i.e., for two vertices $u$, $v$ in different strongly connected components, if there is a directed path from $u$ to $v$, the list contains $u$ appears earlier than the list contains $v$.
TonalidadeHidrica marked this conversation as resolved.
Show resolved Hide resolved
///
/// # Complexity
///
/// - $O(n + m)$ where $m$ is the number of added edges
pub fn scc(&self) -> Vec<Vec<usize>> {
self.internal.scc()
}
Expand Down