 Hi and welcome to this next lecture on data structures and algorithms. We will continue our discussion on shortest path algorithms. In fact, we will continue our discussion for shortest path with a fixed source. However, today we will discuss an algorithm that can deal with negative weighted edges. Recall that we discussed the Deistras algorithm which operates under the constraint that no edge weights are negative. So, the Bellman-Ford algorithm it computes shortest path from a single source, fixed source to all other vertices in a weighted directed graph. However, Deistras algorithm does not work for negative weighted edges. It is a greedy algorithm that makes use of the optimal substructure property. Bellman-Ford solves the problem of negative weighted edges, but is slower than Deistras algorithm that is the price paid and running time is order of number of vertices is to the number of edges. So, what is the idea? So, let us understand the algorithm with a simple example. So, we will try and illustrate the working of the Bellman-Ford algorithm through an example. So, let us say your graph with a source as we will consider a purely directed graph. Let us give names to these vertices v1, v2, v3, v4, v5 and v6. We will also give names to the edges and their weights w1, w2, w3, w4, w5, w6. It also helps to have an additional edge here to make the graph a directed cycle graph. So, let us say this is w7. So, Bellman-Ford algorithm iterates through all the edges of the graph and for every edge it determines the weight on the two nodes that it is part of. So, of course, if you have the edges to be undirected it is possible that the shortest path crosses that particular edge in either way in either direction. However, the edge is directed you expect the shortest path from one node to another node if at all to occur only along the direction that is permitted by the edge. So, the idea behind the Bellman-Ford algorithm is initially all vertices are infinitely far away from the source. The source is of course a distance 0 from itself. Now, you iterate over all edges for each edge E. You are going to check if let us say E is going from U to V. You will check if the distance the shortest path distance to V existing distance is greater than equal to the distance to U plus the weight on the edge U V. If this is the case then you update V to this new found shortest path which says I am going to look at the shortest path to U and then append the edge U V to the shortest path to U. This is the basic idea and you are going to do this for every edge. How many times will you have to do? Well, when you start the iterations initially you determine that for V 1 and V 4 or that is the edges W 1 and W 4 you are able to update the weights for V 1 and V 4 to say W 1 and W 4 respectively. However, for all the other vertices other than source of course in the first iteration over all the edges there is nothing to update. However, in a subsequent iteration you will also update the shortest path for V 2 say which is W 1 plus W 2 and that for V 5 which is W 4 plus W 5. So, you will have to iterate over all the edges number of times that equals the maximum number of hops to a node from S. So, number of times to iterate over all the edges what I mean by this is this iteration and this is the width of graph which is max number of hops from source node S to any vertex say this let us say V by the way we do not need the V 6. So, I am just going to do V 3. So, this is going to be V 3. So, the complexity is basically number of edges into this maximum number of hops, but I will convince you that this maximum number of hops in the worst case actually happens to be number of vertices minus 1. I will construct an example to show this. So, let us consider a simple linear graph S goes to V 1 goes to V 2 goes to V 3. So, my first scan over the edges I will be able to update V 1 the second scan I will be able to update V 2 the third V 3. So, there are 4 vertices and I need 3 scans over all the edges till I am able to reach V 3 and update its shortest path because I can update the shortest path for V 3 when the shortest path for its immediate neighbors are updated. Let us look at the actual algorithm as pointed out the first thing you do is iterate over all the vertices set the depth of every vertex the shortest path to depth to infinity the predecessor for all the nodes is not set, but the predecessor for the source is null and the depth for the source is 0. And then as suggested we are going to iterate over all the edges this inner loop iterate over all the edges and we are going to do that for a number of times that equals number of vertices minus 1. So, recall that this is in the worst case the so called bit of the graph and then it is a check that we already anticipated if du plus w w is the weight of edge e if this happens to be less than the existing shortest path distance to V then you update the shortest path distance at V you also update the predecessor of V to point to U. So, this is already motivated and explained what is the part here at the end but so far we have assumed that our graph is a directed a cyclic graph what if the graph has cycles and is therefore not a directed a cyclic graph abbreviated as dag even in the case that the graph has no directed edges it might just have cycles and here is a test if the shortest path can be further reduced even after V minus 1 iterations then it appears that there is a cycle that is there is a path from S to a node any particular node that involves cycle. Let us illustrate this with an example so we have S V 1 let us say this is weight 5 this is say 4 to V 2 V 3 minus 3 we already pointed out the negative edges are possible and say minus 2 minus 1. Now as you update the weights originating with S 0 V 1 is 5 V 2 is 9 V 3 is 6 and then you have 4 then you have minus 1 is 3. However, the next iteration when you update V 2 we will get 7 and then you will be able to update V 3 to 4 and that at this node V 4 you are able to update the weight for V 4 further and get it to 2 and then at V 1 get it to 1 you could do this again go over this 1 plus 4 is 5 5 minus 3 is 2 2 minus 2 is 0 0 minus 1 is minus 1 and so on. So, just by going around this loop you can actually get very very negative weighted paths from S to all of these nodes. So, what is a characteristic here well it turns out that this cycle itself has negative weight what is the weight of all paths on the cycle minus 1 plus 4 plus minus 3 plus minus 2 the whole weight is basically minus 2. So, the more you go around in this loop the more you will be able to reduce the shortest path and this you can do add infinitum. So, this is what we are checking if after so many iterations if you are still able to reduce the shortest path distance to any particular node then you basically cannot find a shortest path. So, you just return a false. So, that is what we see here returns false for negative weight cycle. Let us see this in action we start with infinite weighted shortest path to all the nodes the first iteration over all the edges we find that only the immediate neighbors of the source can be updated and we have done that then again we look at all the edges we are only able to update now the immediate neighbors of these nodes that we are updated. So, it turns out that B is also unable to A and you are able to get shortest path to B through A this is the latest we continue our bookkeeping find that the shortest path to C and E has been updated C and E has been updated and then to G and it turns out that you can actually find another shortest path G through C and in fact this also lets you update shortest path to E through G. So, let us analyze the Bellman shortest path algorithm we look at two characteristics one is its correctness and the other will be its complexity. So, we prove the correctness of this algorithm by claiming the following loop invariant and we state that for every vertex v within k hops from the source node s the value dv is indeed the shortest path from s after k outer iterations. So, we are claiming that at the kth iteration of this outer loop the value that gets updated in dv the end of this kth iteration dv contain the correct value the shortest path and it is easy to show that at initialization this is correct because the only node that is within 0 hops from the source itself and indeed depth of shortest path of source is set to 0. The next iteration we can easily see that we only deal with the immediate neighbors of the source and they get updated correctly. In fact, the maintenance can be easily proved because we know that to get to a vertex which is k plus 1 hops from the source s you need to go through a vertex which is within k hops from the source s. So, maintenance can be proved with the key observation that a vertex at k plus 1 hops from s is reached vertex at k hops from s and this can therefore extend even a termination. What about time complexity? Well, the runtime complexity is again straightforward as we had anticipated we are going to iterate over all the edges for a fixed outer iteration and number of outer iterations is basically the number of vertices or order of number of vertices. We actually split the cost here for each of the if blocks and the for loops and so on, but it is essentially number of edges into number of vertices and the final check is only order of number of edges which is basically to check for negative weight cycles. So, overall complexity is order of v e is the dominating term. Thank you.