128 lines
No EOL
3.5 KiB
Text
128 lines
No EOL
3.5 KiB
Text
---
|
|
id: BCC-2CC
|
|
title: "BCCs and 2CCs"
|
|
author: Benjamin Qi
|
|
prerequisites:
|
|
- Silver - DFS
|
|
- Platinum - Binary Jumping
|
|
description: "?"
|
|
frequency: 1
|
|
---
|
|
import { Problem } from "../models";
|
|
|
|
export const metadata = {
|
|
problems: {
|
|
sam2: [
|
|
new Problem("YS", "Two-Edge-Connected Components", "two_edge_connected_components", "Easy", false, [], ""),
|
|
],
|
|
disrupt: [
|
|
new Problem("Plat", "Disruption", "842", "Normal", false, ["Merging"]),
|
|
],
|
|
probs2: [
|
|
new Problem("CSA", "One-Way Streets", "one-way-streets", "Easy", false, [], ""),
|
|
],
|
|
bccSam: [
|
|
new Problem("CSES", "Forbidden Cities", "1705", "Normal", false, [], ""),
|
|
],
|
|
gen: [
|
|
new Problem("POI", "Blockade", "https://szkopul.edu.pl/problemset/problem/eDt8w290owtatmCjad0O0ywk/site/?key=statement", "Normal", false, [], ""),
|
|
new Problem("ojuz", "APIO - Duathlon", "APIO18_duathlon", "Normal", false, [], ""),
|
|
new Problem("Plat", "Push a Box", "769", "Very Hard", false, [], ""),
|
|
new Problem("DMOJ", "Investment", "tle17c1p6", "Hard", false, [], ""),
|
|
new Problem("ojuz", "CEOI - Pipes", "CEOI15_pipes", "Hard", false, [], ""),
|
|
],
|
|
}
|
|
};
|
|
|
|
<resources>
|
|
<resource source="CF" title="DFS Tree + Bridges" url="blog/entry/68138"> </resource>
|
|
</resources>
|
|
|
|
## 2-Edge-Connected Components
|
|
|
|
<problems-list problems={metadata.problems.sam2} />
|
|
|
|
(implementation)
|
|
|
|
### With DSU
|
|
|
|
<problems-list problems={metadata.problems.disrupt} />
|
|
|
|
The analysis for the above problem mentions an $O(m\alpha(n))$ solution. Although this is not a two-connected component problem, we can in fact use DSU to generate two-connected components.
|
|
|
|
(explanation?)
|
|
|
|
<spoiler title="Code">
|
|
|
|
The DSU operations take $O(\log n)$ rather than $O(\alpha(n))$ because the DSU does not use union by size, but it's easy to change this.
|
|
|
|
```cpp
|
|
struct TwoEdgeCC {
|
|
struct {
|
|
vi e; void init(int n) { e = vi(n,-1); }
|
|
int get(int x) { return e[x] < 0 ? x : e[x] = get(e[x]); }
|
|
bool unite(int x, int y) { // set par[y] = x
|
|
x = get(x), y = get(y); if (x == y) return 0;
|
|
e[x] += e[y]; e[y] = x; return 1;
|
|
}
|
|
} DSU;
|
|
int N; vector<vi> adj; vi depth, par;
|
|
vpi extra;
|
|
void init(int _N) {
|
|
N = _N; DSU.init(N);
|
|
adj.rsz(N), depth.rsz(N), par = vi(N,-1);
|
|
}
|
|
void dfs(int x) {
|
|
trav(t,adj[x]) if (t != par[x])
|
|
par[t] = x, depth[t] = depth[x]+1, dfs(t);
|
|
}
|
|
void ae(int a, int b) {
|
|
if (DSU.unite(a,b)) adj[a].pb(b), adj[b].pb(a); // edge of forest
|
|
else extra.pb({a,b}); // extra edge
|
|
}
|
|
void ad(int a, int b) {
|
|
while (1) {
|
|
a = DSU.get(a), b = DSU.get(b);
|
|
if (a == b) return;
|
|
if (depth[a] < depth[b]) swap(a,b);
|
|
assert(par[a] != -1 && DSU.unite(par[a],a));
|
|
}
|
|
}
|
|
void gen() {
|
|
F0R(i,N) if (par[i] == -1) dfs(i); // independently for each connected component
|
|
DSU.init(N); trav(t,extra) ad(t.f,t.s); // add non-spanning edges
|
|
}
|
|
};
|
|
```
|
|
|
|
</spoiler>
|
|
|
|
### Problems
|
|
|
|
<problems-list problems={metadata.problems.probs2} />
|
|
|
|
- SRM 787 1000
|
|
|
|
## [Biconnected Components](https://en.wikipedia.org/wiki/Biconnected_component)
|
|
|
|
<problems-list problems={metadata.problems.bccSam} />
|
|
|
|
note that BCCs contain EDGES not VERTICES
|
|
|
|
Related topics include
|
|
|
|
- Articulation Points
|
|
- Bridges
|
|
- Block-Cut Tree
|
|
|
|
### Tutorial
|
|
|
|
<resources>
|
|
<resource source="GFG" title="Articulation Points (aka Cut Vertices)" url="articulation-points-or-cut-vertices-in-a-graph">maybe not completely correct</resource>
|
|
</resources>
|
|
|
|
(implementation)
|
|
|
|
### Problems
|
|
|
|
<problems-list problems={metadata.problems.gen} /> |