ece250: add algs
This commit is contained in:
parent
adedb0c1ad
commit
04adaedfd3
@ -162,3 +162,119 @@ fn sort(A: Vec) {
|
||||
### Directed acyclic graphs
|
||||
|
||||
a DAG is acyclic if and only if there are no **back edges** — edges from a child to an ancestor.
|
||||
|
||||
### Bellman-Ford
|
||||
|
||||
The Bellman-Ford algorithm allows for negative edges and detects negative cycles.
|
||||
|
||||
```rust
|
||||
fn bf(G: Graph, s: Node) {
|
||||
let mut distance = Vec::new(INFINITY);
|
||||
let mut adj_list = Vec::from(G);
|
||||
|
||||
distance[s] = 0;
|
||||
|
||||
for i in 1..G.vertices.len()-1 {
|
||||
for (u,v) in G.edges {
|
||||
if distance[v] > distance[u] + adj_list[u][v] {
|
||||
distance[v] = distance[u] + adj_list[u][v];
|
||||
}
|
||||
}
|
||||
}
|
||||
for (u, v) in G.edges {
|
||||
if distance[v] > distance[u] + adj_list[u][v] {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
### Topological sort
|
||||
|
||||
This is used to find the shortest path in a DAG simply by DFS.
|
||||
|
||||
```rust
|
||||
fn shortest_path(G: Graph, s: Node) {
|
||||
let nodes: Vec<Node> = top_sort(G);
|
||||
let mut adj_list = G.to_adj_list();
|
||||
let mut distance = Vec::new(INFINITY);
|
||||
|
||||
for v in nodes {
|
||||
for adjacent in adj_list[v] {
|
||||
if distance[adjacent] > distance[v] + adjacent[v] {
|
||||
distance[v] = distance[adjacent] + adjacent[v];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
### Minimum spanning tree
|
||||
|
||||
!!! definition
|
||||
- A **cut** $(S, V-S)$ is a partition of vertices into disjoint sets $S$ and $V-S$.
|
||||
- An edge $u,v\in E$ **crosses the cut** $(S,V-S)$ if t`he endpoints are on different sides of the cut.
|
||||
- A cut **respects** a set of edges $A$ if and only if no edge in $A$ crosses the cut.
|
||||
- A **light edge** is the minimum of all edges that could cross the cut. There can be more than one light edge per cut.
|
||||
|
||||
A **spanning tree** of $G$ is a subgraph that contains all of its vertices. An MST minimises the sum of all edges in the spanning tree.
|
||||
|
||||
To create an MST:
|
||||
|
||||
1. Add edges from the spanning tree to an empty set, maintaining that the set is always a subset of an MST (only "safe edges" are added)
|
||||
|
||||
The **Prim-Jarnik algorithm** grows a tree one vertex at a time. $A$ is a subset of the already computed portion of $T$, and all vertices outside $A$ have a weight of infinity if there is no edge.
|
||||
|
||||
```rust
|
||||
// r is the start vertex
|
||||
fn create_mst_prim(G: Graph, r: Vertex) {
|
||||
// clean all vertices
|
||||
for vertex in G.vertices.iter_mut() {
|
||||
vertex.min_weight = INFINITY;
|
||||
vertex.parent = None;
|
||||
}
|
||||
|
||||
let Q = BinaryHeap::from(G.vertices); // priority queue
|
||||
|
||||
while let Some(u) = Q.pop() {
|
||||
for v in u.adjacent_vertices.iter_mut() {
|
||||
if Q.contains(v) && v.edge_to(u).weight < v.min_weight {
|
||||
v.min_weight = v.edge_to(u).weight;
|
||||
Q."modify_key"(v);
|
||||
v.parent = u;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
**Kruskal's algorithm** is objectively better by relying on edges instead.
|
||||
|
||||
```rust
|
||||
fn create_mst_kruskal(G: Graph) -> HashSet<Edge> {
|
||||
let mut A = HashSet::new();
|
||||
let mut S = DisjointSet::new(); // vertices set
|
||||
|
||||
for v in G.vertices.iter() {
|
||||
S.add_as_new_set(v);
|
||||
}
|
||||
G.edges.sort(|edge| edge.weight);
|
||||
|
||||
for (from, dest) in G.edges {
|
||||
if S.find_set_that_contains(from) != S.find_set_that_contains(dest) {
|
||||
A.insert((from, to));
|
||||
let X = S.pop(from);
|
||||
let Y = S.pop(to);
|
||||
S.insert({X.union(Y)});
|
||||
}
|
||||
}
|
||||
return A;
|
||||
}
|
||||
```
|
||||
|
||||
The time complexity is $O(E\log V)$.
|
||||
|
||||
### All pairs shortest path
|
||||
|
||||
Also known as an adjacency matrix extended such that each point represents the minimum distance from one edge to that other edge.
|
||||
|
Loading…
Reference in New Issue
Block a user