E538 Lecture 8
E538 Lecture 8
Systems Engineers
Observations: ● 5, 2, 1
● We start from an empty set of marked nodes and keep adding to it.
● We visit all children of v before moving to v’s grandchildren,
hence the name! (Different than DFS)
● We mark each node only once. We use each edge only once.
USC, Copyright: Arash Saifhashemi, All rights reserved
void MapSetGraph::BFS(int root) {
BFS std::map<int, int> marks;
std::queue<int> q;
● Algorithm Overview: q.push(root);
○ Start from an arbitrary vertex v (call
marks[root] = 1;
it root)
○ Mark v as visited while (!q.empty()) {
○ Visit each neighbor of v that is not int cur = q.front();
marked visited at the current depth, q.pop();
before moving to the next depth.
for (auto &n : edge_map_[cur]) {
■ It is different than topological
sort! if (!marks[n]) {
0 0 1 2 5 5 2 1
0 1 2 5 3 3 5 2
2 5 0 1 2 5 3 3 5
1
3 0 1 2 5 3 3
0 1 2 5 3 4 6 6 4
4 6
0 1 2 5 3 4 6 6
0 1 2 5 3 4 6
USC, Copyright: Arash Saifhashemi, All rights reserved
Breadth First Search 0
Observations:
1
● When we visit root’s children, we are 2
1
1 1 5
discovering all nodes at distance 1.
● When we visit children of a node at distance i, 3
2
we discover all nodes at distance i+1.
0: 0
1: 1
2: 1
3: 2 4 6
4: 3
5: 1
3 3
6: 3
In a graph where all edges have equal weights, BFS finds the shortest distance!
3
Runtime O(m+n) O(m+n)
1 0 1 1
1 1 0 1
1 0 1 Finish
● ● ● ●
● ● ● ●
● ● ● ●
1 0 1 1
1 1 0 1
1 0 1 Finish
1 0 1 1
1 1 0 1
1 0 1 Finish
1 0 1 1
1 1 0 1
1 0 1 Finish
1 3
1 4 1
● The Shortest Path Problem (SPP): find the actual
shortest path between nodes. 4 6
○ Usually we can find path with minor enhancements in
SDP
Important:
Remember:
● Dijkstra ● Floyd–Warshall 4 6
● Bellman-Ford
i j
9
d(i,j)= 9
i j
9
i j
9
d(i,j,{})= 9
i j
d(i,j,k)
1) k d(k
, k - ,j,
k
d (i, k-1
)
i j
d(i,j,k-1)
d(i,j,k) = min(d(i,j,k-1),
d(i,k,k-1)+ d(k,j,k-1))
USC, Copyright: Arash Saifhashemi, All rights reserved
0
Example: 1
3 10
6
0 1 2 3 4 5 6 2 5
1
0 0 3 10 ∞ ∞ 1 ∞ 1
1 3 0 6 1 ∞ ∞ ∞ 1 3
2 10 6 0 1 ∞ ∞ ∞ 1 4 1
3 ∞ 1 1 0 1 ∞ 4
4 6
4 ∞ ∞ ∞ 1 0 ∞ ∞
5 1 ∞ ∞ ∞ ∞ 0 1
6 ∞ ∞ ∞ 4 ∞ 1 0
1 4 1
)
0 1 2 3 4 5 6 0 1 2 3 4 5 6 0 1 2 3 4 5 6 4 6
0 0 3 10 ∞ ∞ 1 ∞ 0 0 3 10 ∞ ∞ 1 ∞ 0 0 3 9 4 ∞ 1 ∞
1 3 0 6 1 ∞ ∞ ∞ 1 3 0 6 1 ∞ 4 ∞ 1 3 0 6 1 ∞ 4 ∞
2 10 6 0 1 ∞ ∞ ∞ 2 10 6 0 1 ∞ 11 ∞ 2 9 6 0 1 ∞ 10 ∞
3 ∞ 1 1 0 1 ∞ 4 3 ∞ 1 1 0 1 ∞ 4 3 4 1 1 0 1 5 4
4 ∞ ∞ ∞ 1 0 ∞ ∞ 4 ∞ ∞ ∞ 1 0 ∞ ∞ 4 ∞ ∞ ∞ 1 0 ∞ ∞
5 1 ∞ ∞ ∞ ∞ 0 1 5 1 4 11 ∞ ∞ 0 1 5 1 4 10 5 ∞ 0 1
6 ∞ ∞ ∞ 4 ∞ 1 0 6 ∞ ∞ ∞ 4 ∞ 1 0 6 ∞ ∞ ∞ 4 ∞ 1 0
shortestPath (i,k,k-1)+shortestPath(k,j,k-1)
USC, Copyright: Arash Saifhashemi, All rights reserved
Floyd-Warshall
// Calculates shortest distance between i,j using nodes 0 to k
long FloydWarshallRecursiveHelper(int i, int j, int k) {
long distance;
if (k < 0) {
return weight_[i][j];
} else {
return std::min(FloydWarshallRecursiveHelper(i, j, k - 1),
FloydWarshallRecursiveHelper(i, k, k - 1) +
FloydWarshallRecursiveHelper(k, j, k - 1));
}
}
i, j, k
f(3) f(4)
f(1) f(0)
Overlapping Subproblems:
i, j, k=n-1
● Dijkstra ● Floyd–Warshall 4 6
4 6
0 1 2 3 4 5 6
u=5 Visited={0} 0 3 10 ∞ ∞ 1 ∞
4 6
0 1 2 3 4 5 6
u=5 Visited={0} 0 3 10 ∞ ∞ 1 ∞
4 6
0 1 2 3 4 5 6
u=5 Visited={0} 0 3 10 ∞ ∞ 1 ∞
Update
u=6 Visited={0,5} 0 3 10 ∞ ∞ 1 2
4 6
0 1 2 3 4 5 6
u=5 Visited={0} 0 3 10 ∞ ∞ 1 ∞
u=6 Visited={0,5} 0 3 10 ∞ ∞ 1 2
4 6
0 1 2 3 4 5 6
u=5 Visited={0} 0 3 10 ∞ ∞ 1 ∞
u=6 Visited={0,5} 0 3 10 ∞ ∞ 1 2
u=1 Visited={0,5,6} 0 3 10 6 ∞ 1 2
4 6
0 1 2 3 4 5 6
u=5 Visited={0} 0 3 10 ∞ ∞ 1 ∞
u=6 Visited={0,5} 0 3 10 ∞ ∞ 1 2
u=1 Visited={0,5,6} 0 3 10 6 ∞ 1 2
u=3 Visited={0,5,6,1} 0 3 9 4 ∞ 1 2
Update
4 6
0 1 2 3 4 5 6
u=5 Visited={0} 0 3 10 ∞ ∞ 1 ∞
u=6 Visited={0,5} 0 3 10 ∞ ∞ 1 2
u=1 Visited={0,5,6} 0 3 10 6 ∞ 1 2
u=3 Visited={0,5,6,1} 0 3 9 4 ∞ 1 2
u=2 Visited={0,5,6,1,3} 0 3 5 4 5 1 2
4 6
0 1 2 3 4 5 6
u=5 Visited={0} 0 3 10 ∞ ∞ 1 ∞
u=6 Visited={0,5} 0 3 10 ∞ ∞ 1 2
u=1 Visited={0,5,6} 0 3 10 6 ∞ 1 2
u=3 Visited={0,5,6,1} 0 3 9 4 ∞ 1 2
u=2 Visited={0,5,6,1,3} 0 3 5 4 5 1 2
4 6
0 1 2 3 4 5 6
u=5 Visited={0} 0 3 10 ∞ ∞ 1 ∞
u=6 Visited={0,5} 0 3 10 ∞ ∞ 1 2
u=1 Visited={0,5,6} 0 3 10 6 ∞ 1 2
u=3 Visited={0,5,6,1} 0 3 9 4 ∞ 1 2
u=2 Visited={0,5,6,1,3} 0 3 5 4 5 1 2
u=4 Visited={0,5,6,1,3,2} 0 3 5 4 5 1 2
4 6
0 1 2 3 4 5 6
u=5 Visited={0} 0 3 10 ∞ ∞ 1 ∞
u=6 Visited={0,5} 0 3 10 ∞ ∞ 1 2
u=1 Visited={0,5,6} 0 3 10 6 ∞ 1 2
u=3 Visited={0,5,6,1} 0 3 9 4 ∞ 1 2
u=2 Visited={0,5,6,1,3} 0 3 5 4 5 1 2
u=4 Visited={0,5,6,1,3,2} 0 3 5 4 5 1 2
Visited={0,5,6,1,3,2,4} 0 3 5 4 5 1 2
visited[source] = true;
visited_size++;
visited[u] = true;
visited_size++;
Source: Wikipedia
N(v1)+N(v2)+...N(vn)= m
Source: Wikipedia
-1
u 1)
1,
d (i- u1
d(i-1, u2)
w(
u2 w(
u1
u
,v
,v d(i, v) is the
)
2
s )
minimum of these
d(i-1, uk)
uk w( paths
u,
k v
)
d(i-1, v) v
uk w(
u,
k v
)
Distance of s to
d(i-1, v) v
v using at most i
edges
if i=0, v=s
0 ;
(i.e. s to itself)
if i=0, v≠s
d(i,v) = ∞ ; (i.e. s to other nodes with
path of size 0)
s
2
t v
-10
f(1,v) = 2
long d = INT_MAX;
for (auto u : pre[v]) {
d = std::min(d, BellmanFordRecursiveHelper(s, i - 1, u) + weight_[u][v]);
}
return std::min(BellmanFordRecursiveHelper(s, i - 1, v), d);
}
}
d(i,v) =
if i=0, v≠s
∞ ;
i, v
i-1, v i - 1, u1 … i - 1, uk
u 1)
1,
d (i- u1 v1
d(i-1, u2)
w(
u2 w(
u1
u
,v
,v v2
)
2
s )
d(i-1, uk)
uk w(
u,
k v
)
d(i-1, v) vj
long d = INT_MAX;
for (auto u : pre[v]) {
d = std::min(d, BellmanFordRecursiveHelper(s, i - 1, u) + weight_[u][v]);
}
return std::min(BellmanFordRecursiveHelper(s, i - 1, v), d);
}
}
i=2
i=2
... ...
i=n-1
i=n-1
Overwrite
2D Table
a = a + 1 1D Table
USC, Copyright: Arash Saifhashemi, All rights reserved
Using 1D Table
std::vector<long> DistMatrixGraph::BellmanFord(int source) {
std::vector<long> d(weight_.size(), INT_MAX);
auto pre = GetPredecessors(); // Map of node to its predecessors
d[source] = 0;
Source: Wikipedia
USC, Copyright: Arash Saifhashemi, All rights reserved
Summary
Shortest Path
Algorithms
Single Source
All Pairs
All other nodes All weights equal
● Dijkstra
● Floyd–Warshall
CANNOT handle negative edges ● BFS
CANNOT handle negative cycles CAN handle negative edges CANNOT handle
O(n^2) OR O((m+n)log(n)) with heap CAN report negative cycles negative edges
Runtime: O(n^3) CANNOT report
● Bellman-Ford negative cycles
Runtime: O(m+n)
CAN handle negative edges
CAN report negative cycles
Runtime: O(m*n)