OfflineDynamicConnectivity

OfflineDynamicConnectivity is a helper for processing graphs with edge insertions and deletions offline.

You register the active time interval [l, r) of each edge.
Then each time point is visited with a RollbackDSU representing the graph state at that time.

Use cases

Typical use cases include:

Idea

Suppose an edge (u, v) is active during the time interval [l, r).

Build a segment tree over time [0, q), and decompose [l, r) into segment tree nodes.
Store the edge on those nodes.

Then DFS over the segment tree:

Each edge is stored in only O(log q) nodes, and each time state is restored efficiently.

Import

import atcoder/extra/graph/offline_dynamic_connectivity

This module also re-exports rollback_dsu.
Inside callbacks, you can use RollbackDSU methods such as same, size, and componentCount.

Types

type OfflineDCEdge = tuple[u, v: int]
type OfflineDynamicConnectivity

Constructor

proc initOfflineDynamicConnectivity(n, q: int): OfflineDynamicConnectivity

Adding active edge intervals

proc addEdgeInterval(dc: var OfflineDynamicConnectivity, l, r, u, v: int)

Registers an undirected edge (u, v) active during the half-open interval [l, r).

Run

proc run(dc: OfflineDynamicConnectivity, f: proc(t: int, uf: RollbackDSU))
proc componentCounts(dc: OfflineDynamicConnectivity): seq[int]

Example

var dc = initOfflineDynamicConnectivity(n = 4, q = 5)# t = 0: 0-1# t = 1: 0-1, 1-2# t = 2: 0-1, 1-2, 2-3# t = 3: 1-2, 2-3# t = 4: 1-2dc.addEdgeInterval(0, 3, 0, 1)dc.addEdgeInterval(1, 5, 1, 2)dc.addEdgeInterval(2, 4, 2, 3)var ans = newSeq[bool](5)dc.run(proc(t: int, uf: RollbackDSU) =  ans[t] = uf.same(0, 3))doAssert ans == @[false, false, true, false, false]

For component counts, use the helper.

doAssert dc.componentCounts == @[3, 2, 1, 2, 3]

Nim-friendly usage

Callbacks and UFCS make per-time queries concise.

dc.run(proc(t: int, uf: RollbackDSU) =
  echo t, ": ", uf.componentCount
)

Complexity

Let q be the number of time points and m be the number of active edge intervals.

RollbackDSU does not use path compression, so merge, same, and size are about O(log n).

Notes