Skip to content

Commit

Permalink
added linked()
Browse files Browse the repository at this point in the history
  • Loading branch information
azizkayumov committed Nov 11, 2023
1 parent f12ce24 commit 109686a
Showing 1 changed file with 47 additions and 15 deletions.
62 changes: 47 additions & 15 deletions src/lctree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,29 @@ impl<P: Path> LinkCutTree<P> {
self.forest.parent_of(v).is_some() || v == w
}

/// Checks if two nodes are connected by a link
/// (i.e. v is the parent of w or vice versa).
///
/// # Examples
/// ```
/// use lctree::LinkCutTree;
///
/// let mut lctree = LinkCutTree::default();
/// let alice = lctree.make_tree(0.0);
/// let bob = lctree.make_tree(0.0);
/// let clay = lctree.make_tree(0.0);
///
/// lctree.link(alice, bob);
/// lctree.link(bob, clay);
///
/// assert!(lctree.linked(alice, bob)); // alice and bob are connected by a link
/// assert!(!lctree.linked(alice, clay)); // alice and clay are not connected by a link
/// ```
pub fn linked(&mut self, v: usize, w: usize) -> bool {
self.connected(v, w);
self.forest.left_of(w) == Some(v) && self.forest.right_of(v).is_none()
}

/// Merges two trees into a single tree.
///
/// # Examples
Expand All @@ -182,12 +205,13 @@ impl<P: Path> LinkCutTree<P> {
/// lctree.link(bob, clay);
/// assert!(lctree.connected(alice, clay));
/// ```
pub fn link(&mut self, v: usize, w: usize) {
if self.connected(v, w) {
return;
pub fn link(&mut self, v: usize, w: usize) -> bool {
if !self.connected(v, w) {
return false;
}
// v is the root of its represented tree:
self.forest.set_left(v, w);
true
}

/// Cuts the link between two nodes (if it exists)
Expand All @@ -207,19 +231,12 @@ impl<P: Path> LinkCutTree<P> {
/// lctree.cut(alice, bob);
/// assert!(!lctree.connected(alice, bob)); // not connected again
/// ```
pub fn cut(&mut self, v: usize, w: usize) {
if !self.connected(v, w) {
return;
}
// detach w from its parent (which is v)
if let Some(left) = self.forest.left_of(w) {
if left != v || self.forest.right_of(v).is_some() {
// maybe this should be a panic?
// eprintln!("Error: no link between {v} and {w}");
return;
}
self.forest.cut_left(w);
pub fn cut(&mut self, v: usize, w: usize) -> bool {
if !self.linked(v, w) {
return false;
}
self.forest.cut_left(w);
true
}

/// Performs path aggregation on a path between two nodes (if they are connected)
Expand Down Expand Up @@ -391,6 +408,21 @@ mod tests {
assert!(lctree.connected(d, a));
}

#[test]
pub fn linked() {
let mut lctree = super::LinkCutTree::default();
let alice = lctree.make_tree(0.0);
let bob = lctree.make_tree(0.0);
let clay = lctree.make_tree(0.0);

lctree.link(alice, bob);
lctree.link(bob, clay);

assert!(lctree.linked(alice, bob));
assert!(lctree.linked(bob, clay));
assert!(!lctree.linked(alice, clay));
}

#[test]
pub fn findroot() {
// We form a link-cut tree from the following rooted tree:
Expand Down

0 comments on commit 109686a

Please sign in to comment.