mirror of
https://github.com/dholerobin/Lecture_Notes.git
synced 2025-07-01 13:06:29 +00:00
commit
b21d836224
442
Akash Articles/Bellman-Ford.md
Normal file
442
Akash Articles/Bellman-Ford.md
Normal file
@ -0,0 +1,442 @@
|
||||
<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"></script>
|
||||
|
||||
## Bellman-Ford Algorithm
|
||||
|
||||
Dijkstra's algorithm solves the problem of finding single source shortest paths, but it does not work in the case if there are negative edges or negative cycles in the graph.
|
||||
|
||||
How do we solve the SSSP problem when the given graph has negative weighted edges?
|
||||
|
||||
We have a new algorithm named "**Bellman-Ford algorithm**" which achieves this goal.
|
||||
|
||||
## Quiz Time
|
||||
You are given a directed graph, how many edges can be there on the path between any two nodes at maximum?
|
||||
|
||||
Answer: $|V|-1$
|
||||
|
||||
## Brute Force
|
||||
|
||||
DFS finds out the correct shortest path whether the edge weights are positive or negative, because it searches all the possible paths from the source to the destination.
|
||||
**Note:** If there is a negative cycle, then it is not possible to find the shortest distance to affected vertices.
|
||||
|
||||
## Bellman-Ford algorithm
|
||||
|
||||
Bellman-Ford algorithm works on the principal that the path between any two vertices can contain at most $|V|$ vertices or $|V|-1$ edges.
|
||||
|
||||
In Bellman-Ford Algorithm, the main step is the relaxation of the edges.
|
||||
|
||||
The algorithm relaxes all the outgoing directed edges $|V| - 1$ times.
|
||||
|
||||
### Algorithm
|
||||
|
||||
1. Same as Dijkstra's Algorithm, mark all the distances to $\infty$ and assign all the parent vertices to some sentinel value (not used before).
|
||||
2. Assign source to source distance as $0$ and start the algorithm.
|
||||
3. Loop over all the directed edges.
|
||||
4. If the relaxation condition below is satisfied, then relax those edges.
|
||||
**Relaxation Condition:** For an edge from $A \to B$,
|
||||
$$\text{Distance}[B] < \text{Distance}[A] + \text{EdgeWeight}[A, B]$$
|
||||
5. Repeat the step 3, $|V|-1$ times.
|
||||
|
||||
This is a kind of bottom-up **Dynamic Programming**. After the $k$-th iteration of the outer loop the shortest paths having at most $k$ edges are found.
|
||||
|
||||
### Visualization
|
||||
|
||||
|
||||
|
||||
After the first iteration of the outer loop there will not be any more relaxations.
|
||||
|
||||
### Code
|
||||
|
||||
```c++
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define MAX_DIST 100000000
|
||||
|
||||
// Function to print the required path
|
||||
void printpath(vector<int>& parent, int vertex, int source, int destination)
|
||||
{
|
||||
if(vertex == source)
|
||||
{
|
||||
cout << source << "-->";
|
||||
return;
|
||||
}
|
||||
printpath(parent, parent[vertex], source, destination);
|
||||
|
||||
cout << vertex << (vertex==destination ? "\n" : "-->");
|
||||
}
|
||||
|
||||
// Object - Edge
|
||||
struct edge{
|
||||
|
||||
// Edge from -> to
|
||||
// having some weight
|
||||
int from, to, weight;
|
||||
|
||||
edge(int a, int b, int w)
|
||||
{
|
||||
from = a;
|
||||
to = b;
|
||||
weight = w;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
int no_vertices=5;
|
||||
|
||||
// Array of edges
|
||||
vector<edge> edges;
|
||||
|
||||
// Distance and Parent vertex storing arrays
|
||||
vector<int> distance(no_vertices+1, MAX_DIST), parent(no_vertices+1,-1);
|
||||
|
||||
// Edges
|
||||
edges.push_back(edge(1,2,1));
|
||||
edges.push_back(edge(2,3,1));
|
||||
edges.push_back(edge(1,3,2));
|
||||
edges.push_back(edge(2,4,-10));
|
||||
edges.push_back(edge(4,3,4));
|
||||
edges.push_back(edge(3,5,1));
|
||||
|
||||
// For the shake of example
|
||||
int source = 1, destination = 5;
|
||||
|
||||
distance[1] = 0;
|
||||
|
||||
// Bellman-Ford Algorithm
|
||||
for (int i = 0; i < no_vertices - 1; i++)
|
||||
{
|
||||
// Loop over all the edges
|
||||
for(int j = 0; j < edges.size() ; j++)
|
||||
{
|
||||
if(distance[edges[j].from] != MAX_DIST) {
|
||||
|
||||
// Check for the Relaxation Condition
|
||||
if(distance[edges[j].to] > distance[edges[j].from] + edges[j].weight )
|
||||
{
|
||||
distance[edges[j].to] = distance[edges[j].from] + edges[j].weight;
|
||||
parent[edges[j].to] = edges[j].from;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shortest distance from source to destination
|
||||
cout << distance[5] << endl;
|
||||
|
||||
// Shortest path
|
||||
printpath(parent, 5, 1, 5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
### Time Complexity
|
||||
|
||||
- $\mathcal{O}(|V| )$ time is taken by outer loop as it runs $|V|-1$ times.
|
||||
- $\mathcal{O}(|E|)$ time to loop over all the edges in the inner loop.
|
||||
|
||||
So the total time complexity will be: $\mathcal{O}(| V | \cdot | E |)$
|
||||
|
||||
If there is a negative cycle in the graph, then certainly we can not find the shortest paths. But how to detect the negative cycles?
|
||||
|
||||
We can use Bellman-Ford algorithm to detect negative cycles in the graph. How?
|
||||
|
||||
## Detection of Negative Cycle
|
||||
|
||||
In the algorithm, we are running the outer loop $|V| - 1$times, as there can be at most $|V| - 1$ relaxations on a path between any two vertices.
|
||||
|
||||
Now, if there are any more relaxations possible, then there is a negative cycle in the graph. This is how we detect the negative cycle.
|
||||
|
||||
So, we will run the outer loop one more time to detect the negative cycle.
|
||||
|
||||
```c++
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define MAX_DIST 100000000
|
||||
|
||||
// Function to print the required path
|
||||
void printpath(vector<int>& parent, int vertex, int source, int destination)
|
||||
{
|
||||
if(vertex == source)
|
||||
{
|
||||
cout << source << "-->";
|
||||
return;
|
||||
}
|
||||
|
||||
printpath(parent, parent[vertex], source, destination);
|
||||
|
||||
cout << vertex << (vertex==destination ? "\n" : "-->");
|
||||
}
|
||||
|
||||
// Object of Edge
|
||||
struct edge{
|
||||
|
||||
// Edge from -> to
|
||||
// having some weight
|
||||
int from, to, weight;
|
||||
|
||||
edge(int a, int b, int w)
|
||||
{
|
||||
from = a;
|
||||
to = b;
|
||||
weight = w;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Bellman-Ford Algorithm for Negative Cycle
|
||||
bool Bellman_Ford_NC(vector<edge> & edges, vector<int> & distance, vector<int> & parent)
|
||||
{
|
||||
int no_vertices = 5;
|
||||
|
||||
for (int i = 0; i < no_vertices - 1; i++)
|
||||
{
|
||||
// Loop over all the edges
|
||||
for(int j = 0; j < edges.size() ; j++)
|
||||
{
|
||||
if(distance[edges[j].from] != MAX_DIST)
|
||||
{
|
||||
// Check for the Relaxation Condition
|
||||
if(distance[edges[j].to] > distance[edges[j].from] + edges[j].weight )
|
||||
{
|
||||
distance[edges[j].to] = distance[edges[j].from] + edges[j].weight;
|
||||
parent[edges[j].to] = edges[j].from;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_negative_cycle = false;
|
||||
|
||||
// Running the outer loop one more time
|
||||
for(int j = 0; j < edges.size() ; j++)
|
||||
{
|
||||
// Check for the Relaxation Condition
|
||||
if(distance[edges[j].to] > distance[edges[j].from] + edges[j].weight )
|
||||
{
|
||||
// Used when finding vertices in NC
|
||||
distance[edges[j].to] = distance[edges[j].from] + edges[j].weight;
|
||||
parent[edges[j].to] = edges[j].from;
|
||||
// There is a negative cycle
|
||||
is_negative_cycle = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(is_negative_cycle)
|
||||
{
|
||||
cout << "There is a negative cycle in the graph." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
int no_vertices=5;
|
||||
|
||||
// Array of edges
|
||||
vector<edge> edges;
|
||||
|
||||
// Distance and Parent vertex storing arrays
|
||||
vector<int> distance(no_vertices+1, MAX_DIST), parent(no_vertices+1,-1);
|
||||
|
||||
// Edges
|
||||
edges.push_back(edge(1,2,1));
|
||||
edges.push_back(edge(2,3,5));
|
||||
edges.push_back(edge(3,1,2));
|
||||
edges.push_back(edge(2,4,-10));
|
||||
edges.push_back(edge(4,3,4));
|
||||
edges.push_back(edge(3,5,1));
|
||||
|
||||
// For the shake of example
|
||||
int source = 1, destination = 5;
|
||||
|
||||
distance[1] = 0;
|
||||
|
||||
if(Bellman_Ford(edges, distance, parent))
|
||||
{
|
||||
// Shortest distance from source to destination
|
||||
cout << distance[5] << endl;
|
||||
|
||||
// Shortest path
|
||||
printpath(parent, 5, 1, 5);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
Is it possible to find the vertices involved in the negative cycle? Yes.
|
||||
|
||||
## Finding the Negative Cycle
|
||||
|
||||
If there is a unique negative cycle, then we can find out the vertices involved in the cycle using the data of the last relaxation edge and parent vertices.
|
||||
|
||||
```c++
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define MAX_DIST 100000000
|
||||
|
||||
// Function to print the required path
|
||||
void printpath(vector<int>& parent, int vertex, int source, int destination)
|
||||
{
|
||||
if(vertex == source)
|
||||
{
|
||||
cout << source << "-->";
|
||||
return;
|
||||
}
|
||||
printpath(parent, parent[vertex], source, destination);
|
||||
|
||||
cout << vertex << (vertex==destination ? "\n" : "-->");
|
||||
}
|
||||
|
||||
// Function to print the required path
|
||||
void printcycle(vector<int>& parent, int vertex, int source, int destination)
|
||||
{
|
||||
if(vertex == source)
|
||||
{
|
||||
cout << source << "-->";
|
||||
return;
|
||||
}
|
||||
printcycle(parent, parent[vertex], source, destination);
|
||||
|
||||
if(vertex == destination)
|
||||
cout << vertex << "-->" << source << endl;
|
||||
else
|
||||
cout << vertex << "-->";
|
||||
}
|
||||
|
||||
// Object - Edge
|
||||
struct edge{
|
||||
|
||||
// Edge from -> to
|
||||
// having some weight
|
||||
int from, to, weight;
|
||||
|
||||
edge(int a, int b, int w)
|
||||
{
|
||||
from = a;
|
||||
to = b;
|
||||
weight = w;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Bellman-Ford Algorithm
|
||||
bool Bellman_Ford(vector<edge> & edges, vector<int> & distance, vector<int> & parent)
|
||||
{
|
||||
int no_vertices = 5;
|
||||
for (int i = 0; i < no_vertices - 1; i++)
|
||||
{
|
||||
// Loop over all the edges
|
||||
for(int j = 0; j < edges.size() ; j++)
|
||||
{
|
||||
if(distance[edges[j].from] != MAX_DIST)
|
||||
{
|
||||
|
||||
// Check for the Relaxation Condition
|
||||
if(distance[edges[j].to] > distance[edges[j].from] + edges[j].weight )
|
||||
{
|
||||
distance[edges[j].to] = distance[edges[j].from] + edges[j].weight;
|
||||
parent[edges[j].to] = edges[j].from;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_negative_cycle = false;
|
||||
|
||||
int last_relaxation = 0;
|
||||
|
||||
// Running the outer loop one more time
|
||||
for(int j = 0; j < edges.size() ; j++)
|
||||
{
|
||||
// Check for the Relaxation Condition
|
||||
if(distance[edges[j].to] > distance[edges[j].from] + edges[j].weight )
|
||||
{
|
||||
distance[edges[j].to] = distance[edges[j].from] + edges[j].weight;
|
||||
parent[edges[j].to] = edges[j].from;
|
||||
last_relaxation = edges[j].to;
|
||||
is_negative_cycle = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(is_negative_cycle)
|
||||
{
|
||||
cout << "There is a negative cycle in the graph." << endl;
|
||||
return last_relaxation;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
int no_vertices=5;
|
||||
|
||||
// Array of edges
|
||||
vector<edge> edges;
|
||||
|
||||
// Distance and Parent vertex storing arrays
|
||||
vector<int> distance(no_vertices+1, MAX_DIST), parent(no_vertices+1,-1);
|
||||
|
||||
// Edges
|
||||
edges.push_back(edge(1,2,1));
|
||||
edges.push_back(edge(2,3,5));
|
||||
edges.push_back(edge(3,1,2));
|
||||
edges.push_back(edge(2,4,-10));
|
||||
edges.push_back(edge(4,3,4));
|
||||
edges.push_back(edge(3,5,1));
|
||||
|
||||
// For the shake of example
|
||||
int source = 1, destination = 5;
|
||||
|
||||
distance[1] = 0;
|
||||
|
||||
int last_relaxation = Bellman_Ford(edges, distance, parent);
|
||||
|
||||
if(!last_relaxation)
|
||||
{
|
||||
// Shortest distance from source to destination
|
||||
cout << distance[5] << endl;
|
||||
|
||||
// Shortest path
|
||||
printpath(parent, 5, 1, 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
int trapped = last_relaxation;
|
||||
|
||||
// To find the negative_cycle, we can
|
||||
// use the last relaxation data
|
||||
// and loop back over parent vertices
|
||||
// for over no_vertices time, so that
|
||||
// we get trapped in the negative cycle
|
||||
for(int i = 0; i < no_vertices; i++)
|
||||
{
|
||||
trapped = parent[trapped];
|
||||
}
|
||||
|
||||
// Printing negative_cycle
|
||||
printcycle(parent, parent[trapped], trapped, parent[trapped]);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Other Shortest Path finding Algorithms
|
||||
|
||||
1. All pair shortest path algorithm - **Floyd Warshall Algorithm**.
|
||||
2. SSSP using Dynamic Programming.
|
||||
3. Dijkstra's Algorithm
|
374
Akash Articles/Dijkstra.md
Normal file
374
Akash Articles/Dijkstra.md
Normal file
@ -0,0 +1,374 @@
|
||||
<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"></script>
|
||||
|
||||
|
||||
## Dijkstra's Algorithm
|
||||
|
||||
Have you ever used Google Maps?
|
||||
|
||||
Ever wondered how it works? How does it tell you the shortest path from point A to B?
|
||||
|
||||
At the backside of it, they are using something known as "Shortest Path Finding algorithm". Well, what does the shortest path actually mean?
|
||||
|
||||
The **dark** line represents the shortest path from the home to the office, in the diagram below
|
||||

|
||||
|
||||
Do you know how to represent the roads between different places? This is **Weighted Directed Graph** - a directed graph with edges having weights.
|
||||
|
||||
## Quiz Time:
|
||||
|
||||
Now can you find the shortest path from the source vertex to the target vertex in the image below?
|
||||
|
||||

|
||||
|
||||
Answer: The dark line shows the answer.
|
||||
|
||||

|
||||
|
||||
-- --
|
||||
Single Source Shortest Path problem (SSSP)
|
||||
-----------------------------
|
||||
**Statement**: Given a graph find out the shortest path from a given point to all other points.
|
||||
|
||||
### How to solve this problem?
|
||||
When we talk about the graph we have two standard techniques to traverse: DFS and BFS.
|
||||
|
||||
Can you solve this problem using these standard algorithms?
|
||||
|
||||
Certainly. We will see how to find the shortest path from the source to the destination using DFS.
|
||||
|
||||
Let's look at how can we solve it using DFS.
|
||||
|
||||
|
||||
### Solution using DFS:
|
||||
|
||||
**Algorithm:** DFS approach is very simple.
|
||||
|
||||
- Start from the source vertex
|
||||
- Explore all the vertices adjacent to the source vertex
|
||||
- For each adjacent vertex, If it satisfies the relaxation condition then update the new distance and parent vertex
|
||||
- Then recurse on it, by considering itself as the new source.
|
||||
|
||||
**Relaxation** means if you reach the vertex with less distance than encountered before, then update the data. **Parent vertex** means the vertex by which the particular vertex is reached.
|
||||
|
||||
This way DFS will explore all the possible paths from the source vertex to the destination vertex and will find out the shortest path.
|
||||
|
||||
Here in the code, we will represent the graph using adjacency list representation:
|
||||
|
||||
```c++
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define MAX_DIST 100000000
|
||||
|
||||
// Function to print the required path
|
||||
void printpath(vector<int>& parent, int vertex, int source, int destination)
|
||||
{
|
||||
if(vertex == source)
|
||||
{
|
||||
cout << source << "-->";
|
||||
return;
|
||||
}
|
||||
printpath(parent, parent[vertex], source, destination);
|
||||
cout << vertex << (vertex==destination ? "\n" : "-->");
|
||||
}
|
||||
|
||||
void DFS(int source, int destination, vector<vector<pair<int,int> > > &graph, vector<int> &distances, vector<int> &parent)
|
||||
{
|
||||
// When we reach at the destination just return
|
||||
if(source == destination)
|
||||
return;
|
||||
|
||||
// Do DFS over all the vertices connected
|
||||
// with the source vertex
|
||||
for(auto vertex: graph[source])
|
||||
{
|
||||
// Relaxation of edge:
|
||||
// If the distance is less than what we
|
||||
// have encountered uptil now then update
|
||||
// Distance and Parent vertex
|
||||
if(distances[vertex.second] > distances[source] + vertex.first)
|
||||
{
|
||||
distances[vertex.second] = distances[source] + vertex.first;
|
||||
parent[vertex.second] = source;
|
||||
}
|
||||
|
||||
// Do DFS over all the vertices connected
|
||||
// with the source vertex
|
||||
DFS(vertex.second, destination, graph, distances, parent);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Number of vertices in graph
|
||||
int n = 6;
|
||||
|
||||
// Adjacency list representation of the
|
||||
// Directed Graph
|
||||
vector<vector<pair<int, int> > > graph;
|
||||
|
||||
graph.assign(n + 1, vector<pair<int, int> >());
|
||||
|
||||
// Now make the Directed Graph
|
||||
// Note that edges are
|
||||
// in the form (weight, vertex ID)
|
||||
graph[1].push_back( make_pair(1, 2) );
|
||||
graph[1].push_back( make_pair(6, 2) );
|
||||
graph[2].push_back( make_pair(1, 4) );
|
||||
graph[4].push_back( make_pair(1, 3) );
|
||||
graph[3].push_back( make_pair(1, 5) );
|
||||
graph[2].push_back( make_pair(7, 5) );
|
||||
graph[4].push_back( make_pair(3, 6) );
|
||||
|
||||
// Array to store the distances
|
||||
vector<int> distances(n+1, MAX_DIST);
|
||||
|
||||
// Array to store the parent vertices
|
||||
vector<int> parent(n+1, -1);
|
||||
|
||||
int source = 1, destination = 5;
|
||||
|
||||
distances[source] = 0;
|
||||
|
||||
// Do DFS
|
||||
DFS(source, destination, graph, distances, parent);
|
||||
|
||||
int shortest_distance = distances[destination];
|
||||
|
||||
// To print shortest_distance
|
||||
cout << shortest_distance << endl;
|
||||
|
||||
// To print the path of the shortest_distance
|
||||
printpath(parent, destination, source, destination);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Time Complexity of DFS
|
||||
As DFS explores all possible paths from the given source vertex to the destination vertex, this may lead to exponential time complexity in a very dense graph.
|
||||
|
||||
So, our DFS approach is not efficient. What next?
|
||||
|
||||
We have a very interesting and elegant algorithm to solve the problem named " **Dijkstra's Algorithm**". This is the algorithm whose variants are used by most of the path finding applications.
|
||||
|
||||
## Dijkstra's Algorithm:
|
||||
|
||||
Dijkstra's Algorithm solves SSSP.
|
||||
|
||||
Dijkstra's Algorithm is an iterative algorithm similar to **BFS**, but here we have a little twist.
|
||||
|
||||
**Algorithm:**
|
||||
|
||||
1. Mark the distance between the source and all other vertices to $\infty$ and assign all the parent vertices to some sentinel (not used value).
|
||||
2. The set is a collection of vertices which is empty at the start of the algorithm.
|
||||
3. Set the distance between source to source as 0 and add the source vertex to the set.
|
||||
4. Find the minimum distance vertex from the set and erase it from the set. Mark it as processed. let this vertex be $A$.
|
||||
5. Explore all the edges connected to $A$.
|
||||
6. If the edge is connected to the unprocessed vertex and it satisfies the relaxation condition below, then relax that edge and insert the vertex into the set.
|
||||
**Relaxation Condition:** Let the edge be $A-u$,
|
||||
$$\text{Distance}[u] < \text{Distance}[A] + \text{EdgeWeight}(A,u)$$
|
||||
4. If the set is empty, then stop the algorithm.
|
||||
5. Otherwise, repeat from step 3.
|
||||
|
||||
In Dijkstra's Algorithm, we explore the vertices in the way BFS does, however here we have to find the minimum distance vertex from the set.
|
||||
|
||||
Which data structure can help us find the minimum distance vertex from the set?
|
||||
|
||||
**Priority Queue** is the data structure which achieves this goal in an efficient manner $\mathcal{O}(\log n)$.
|
||||
|
||||
**Visualization:**
|
||||
|
||||
- Here cloud represents the processed nodes - the nodes whose final shortest distance is found.
|
||||
- Solid lines represent the edges that are discovered.
|
||||
- Numbers in square brackets represent the current distance of that vertex from the source vertex.
|
||||
|
||||
|
||||
1. Start from the source vertex 1. 
|
||||
2. Vertex 1 discovers vertices 2 and 3. It consequently does the relaxation and adds vertices 2 and 3 in the set.
|
||||

|
||||
3. The minimum distance vertex in the set is vertex 2. So vertex 2 will be the next source vertex.
|
||||
|
||||
It will discover vertices 5 and 4.
|
||||
|
||||
Now vertex 2 is added to the cloud as it is processed.
|
||||

|
||||
4. The next minimum distance vertex is vertex 4.
|
||||
It relaxes both 3 and 6. Then vertex 4 will be added to the cloud.
|
||||

|
||||
5. Next vertex will be 3. It relaxes 5.
|
||||

|
||||
6. Now there will not be any more relaxations.
|
||||
All the vertices in the priority queue will dequeue without adding any new vertex to the set.
|
||||

|
||||
|
||||
Now we have found the shortest distances to all the vertices from the given source vertex.
|
||||
|
||||
We can use parent array to store parent of the given vertex, and then we can find out the shortest path for any vertex.
|
||||
|
||||
```c++
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define MAX_DIST 100000000
|
||||
|
||||
// Function to print the required path
|
||||
void printpath(vector<int>& parent, int vertex, int source, int destination)
|
||||
{
|
||||
if(vertex == source)
|
||||
{
|
||||
cout << source << "-->";
|
||||
return;
|
||||
}
|
||||
printpath(parent, parent[vertex], source, destination);
|
||||
|
||||
cout << vertex << (vertex==destination ? "\n" : "-->");
|
||||
}
|
||||
|
||||
|
||||
// Dijkstra's Algorithm
|
||||
int Dijkstra_Algo(vector<vector<pair<int, int> > >& Graph,
|
||||
int src, int target, vector<int> & distances, vector<int> & parent)
|
||||
{
|
||||
|
||||
// Minimum Priority Queue to keep track of the discovered
|
||||
// vertex which has the minimum distance
|
||||
priority_queue<pair<int, int>, vector<pair<int, int> >,
|
||||
greater<pair<int, int> > > container;
|
||||
|
||||
// To check whether vertex is in the cloud
|
||||
vector<bool> processed(Graph.size());
|
||||
|
||||
// Start with source vertex
|
||||
// Push the source vertex in the
|
||||
// Priority Queue
|
||||
container.push(make_pair(0, src));
|
||||
|
||||
// Assign distance to source as 0
|
||||
distances[src] = 0;
|
||||
|
||||
|
||||
while (!container.empty()) {
|
||||
|
||||
// Pop the least distance vertex from the Priority Queue
|
||||
pair<int, int> temp = container.top();
|
||||
int current_src = temp.second;
|
||||
|
||||
// Pop the minimum distance vertex
|
||||
container.pop();
|
||||
|
||||
processed[current_src] = true;
|
||||
// current source vertex
|
||||
for (auto vertex : Graph[current_src]) {
|
||||
|
||||
// Distance of the vertex from its
|
||||
// temporary source vertex
|
||||
int distance = distances[current_src] + vertex.first;
|
||||
|
||||
// Relaxation of edge
|
||||
if (!processed[vertex.second] && distance < distances[vertex.second]) {
|
||||
|
||||
// Updating the distance
|
||||
distances[vertex.second] = distance;
|
||||
|
||||
// Updating the parent vertex
|
||||
parent[vertex.second] = current_src;
|
||||
|
||||
// Adding the relaxed edge in the prority queue
|
||||
container.push(make_pair(distance, vertex.second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return the shortest distance
|
||||
return distances[target];
|
||||
}
|
||||
int main()
|
||||
{
|
||||
// Number of vertices in graph
|
||||
int n = 6;
|
||||
|
||||
// Adjacency list representation of the
|
||||
// Directed Graph
|
||||
vector<vector<pair<int, int> > > graph;
|
||||
|
||||
graph.assign(n + 1, vector<pair<int, int> >());
|
||||
|
||||
// Now make the Directed Graph
|
||||
// Note that edges are
|
||||
// in the form (weight, vertex ID)
|
||||
graph[1].push_back( make_pair(1, 2) );
|
||||
graph[1].push_back( make_pair(6, 2) );
|
||||
graph[2].push_back( make_pair(1, 4) );
|
||||
graph[4].push_back( make_pair(1, 3) );
|
||||
graph[3].push_back( make_pair(1, 5) );
|
||||
graph[2].push_back( make_pair(7, 5) );
|
||||
graph[4].push_back( make_pair(3, 6) );
|
||||
|
||||
// Array to store the distances
|
||||
vector<int> distances(n+1, MAX_DIST);
|
||||
|
||||
// Array to store the parent vertices
|
||||
vector<int> parent(n+1, -1);
|
||||
|
||||
// For example destination is taken as 5
|
||||
int source = 1, destination = 5;
|
||||
|
||||
distances[source] = 0;
|
||||
|
||||
// Dijkstra's algorithm
|
||||
int shortest_distance = Dijkstra_Algo(graph, source, destination, distances, parent);
|
||||
|
||||
// To print shortest_distance
|
||||
cout << shortest_distance << endl;
|
||||
|
||||
// To print the path of the shortest_distance
|
||||
printpath(parent, destination, source, destination);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
## Time Complexity of Dijkstra's Algorithm:
|
||||
|
||||
1. $\mathcal{O}(|E|)$ time to make the Weighted Directed Graph.
|
||||
2. $\mathcal{O}(|E| + |V|)$ can be taken by the while loop which is similar to BFS time complexity.
|
||||
3. $\mathcal{O}(\log |V|)$ time to insert the relaxed vertex in the priority queue.
|
||||
|
||||
So the overall complexity of the Dijkstra's Algorithm will be
|
||||
$$\mathcal{O}((|E| + |V|) \times \log(|V|))$$
|
||||
|
||||
Here $|E|$ represents the number of edges in the graph and $|V|$ represents the number of vertices in the graph.
|
||||
|
||||
|
||||
## Limitation of Dijkstra's Algorithm:
|
||||
|
||||
When there are negative weight edges in the graph, then Dijkstra's algorithm does not work.
|
||||
|
||||
Example:
|
||||

|
||||
|
||||
It will find the path from $a$ to $c$ incorrectly.
|
||||
|
||||
What if there is a negative cycle in the graph?
|
||||
|
||||
**Negative Cycle:** Cycle in which sum of the weights of the edges is negative.
|
||||
|
||||
When there is any negative cycle in the graph then Dijkstra's algorithm will run forever, because then we can reach the affected vertices in negative infinite cost.
|
||||
|
||||
Note that the graph, we have used, is connected. If you have a vertex which is not connected, then you cannot find the shortest distance to it!
|
||||
|
||||
## **Applications of Dijkstra's algorithm:**
|
||||
|
||||
|
||||
1. One very famous variant is the "Widest Path Finding Algorithm", which is an algorithm to finding a path between two vertices of the graph **maximizing the weight of the minimum-weight edge in the path**.
|
||||
|
||||
In the practical application, this problem can be seen as a graph with routers as its vertices and edges representing bandwidth between two vertices. Now if we want to find the maximum bandwidth path between two places in the internet connection, then this algorithm is useful which is highly based on Dijkstra's Algorithm.
|
||||
|
||||
2. A widely used application of the shortest path algorithm is in network routing protocols "Routing protocol".
|
||||
|
||||
## Other Shortest Path Finding Algorithms:
|
||||
|
||||
1 Bellman-Ford Algorithm
|
||||
2. Using Dynamic Programming
|
||||
3. All Pair Shortest Path Algorithm - **Floyd-Warshall Algorithm**, which finds the shortest path between every pair of vertices.
|
||||
|
291
Akash Articles/Floyd-Warshall.md
Normal file
291
Akash Articles/Floyd-Warshall.md
Normal file
@ -0,0 +1,291 @@
|
||||
## All Pair Shortest Path Problem
|
||||
|
||||
Statement: Given a graph, Find out the shortest distance paths between every pair of vertices.
|
||||
|
||||
## Brute Force
|
||||
|
||||
We have seen Dijkstra's algorithm and Bellman-Ford algorithm, which solves the SSSP problem.
|
||||
|
||||
We can run these algorithms for every vertex one by one, which solves the given problem.
|
||||
|
||||
This will give the complexity of $\mathcal{O}( (|V| + |E|) \cdot |V| \cdot log|V|)$ in the case of Dijkstra's algorithm and $\mathcal{O} (|V|^2 \cdot |E|)$ in the case of Bellman-Ford Algorithm.
|
||||
|
||||
**Floyd-Warshall Algorithm** solves all pair shortest path problem in an efficient manner.
|
||||
|
||||
## Floyd-Warshall Algorithm
|
||||
|
||||
This algorithm is an example of Dynamic Programming. We split the process of finding the shortest paths in several phases.
|
||||
|
||||
-- --
|
||||
|
||||
### Quiz Time
|
||||
|
||||
You are given that the shortest path between two vertices $A$ and $B$ passes through $C$, i.e. $C$ is the intermediate vertex in the shortest path from $A$ to $B$. What can you conclude from it?
|
||||
|
||||
Answer: $SD(A, B) = SD(A,C) + SD(C,B)$
|
||||
|
||||
$SD$ stands for Shortest Distance.
|
||||
|
||||
-- --
|
||||
|
||||
The above answer can be proved using contradiction.
|
||||
|
||||
The Floyd-Warshall algorithm works based on the above answer.
|
||||
|
||||
Before the $i^{th}$ phase of the algorithm, it finds out the shortest distance path between every pair of vertices which uses intermediate vertices only from the set $\{1,2,..,i-1\}$. In every phase of the algorithm, we add one more vertex in the set.
|
||||
|
||||
In the $i^{th}$ phase, we update the $distance$ matrix considering the two cases below:
|
||||
|
||||
For an entry $distance[a][b]$,
|
||||
|
||||
1. If the shortest path between $a$ and $b$ which uses intermediate vertices from the set $\{1,2,...i-1\}$ is longer than the one that uses $\{1,2,...,i\}$, then update the shortest distance path as below:
|
||||
|
||||
$distance[a][b] = distance[a][i]+distance[i][b]$
|
||||
|
||||
Where $distance[a][b]$ is the shortest distance between $a$ and $b$ which uses intermediate vertices from the set $\{1,2,..,i-1\}$.
|
||||
|
||||
2. Otherwise, $distance[a][b]$ will remain unchanged.
|
||||
|
||||
### Algorithm
|
||||
|
||||
1. Initialize $N \times N$ distance matrix with infinity.
|
||||
2. Assign every element representing distance between vertex to itself to zero - assign every diagonal element of distance matrix to zero.
|
||||
3. For all pair of vertices, If there is an edge between $A$ and $B$, then update $distance[A][B]$ to $Edge Weight(A,B)$.
|
||||
4. Start from the first vertex, say phase $i=1$.
|
||||
5. For all pairs of the vertices, update the new shortest distance between them using the condition below,
|
||||
$distance[a][b] > distance[a][i]+distance[i][b]$
|
||||
6. If $i$ is equal to the number of vertices, then stop otherwise increment $i$ and repeat step $5$.
|
||||
|
||||
```c++
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define MAX_DIST 100000000
|
||||
|
||||
|
||||
void Floyd_Warshall(int no_vertices, vector<vector<int> > & distances)
|
||||
{
|
||||
// i shows the phase
|
||||
for(int i = 1; i <= no_vertices; i++)
|
||||
{
|
||||
// Update distance matrix for all pairs
|
||||
for(int a = 1; a <= no_vertices; a++)
|
||||
{
|
||||
for(int b = 1; b <= no_vertices; b++)
|
||||
{
|
||||
if(distances[a][i] < MAX_DIST && distances[i][b] < MAX_DIST)
|
||||
distances[a][b] = min(distances[a][b], distances[a][i]+distances[i][b]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
int no_vertices=5;
|
||||
|
||||
// N*N array to store the distances between every pair
|
||||
vector<vector<int> > distances(no_vertices+1, vector<int> (no_vertices+1, MAX_DIST));
|
||||
|
||||
// Adding the edges virtually by
|
||||
// updating distance matrix
|
||||
distances[1][2]=1;
|
||||
distances[1][3]=-3;
|
||||
distances[2][4]=2;
|
||||
distances[2][5]=1;
|
||||
distances[3][4]=-1;
|
||||
distances[3][5]=2;
|
||||
distances[4][5]=1;
|
||||
|
||||
for(int i = 1; i <= no_vertices; i++)
|
||||
distances[i][i] = 0;
|
||||
|
||||
Floyd_Warshall(no_vertices, distances);
|
||||
|
||||
// Printing the distance matrix
|
||||
for(int i=1;i<=no_vertices;i++)
|
||||
{
|
||||
for(int j=1;j<=no_vertices;j++)
|
||||
{
|
||||
if(distances[i][j]!=MAX_DIST)
|
||||
cout << setw(5) << right << distances[i][j] << " ";
|
||||
else
|
||||
cout << setw(5) << right << "INF" << " ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Time Complexity
|
||||
As there are three loops, each running number of vertices time, the complexity will be $\mathcal{O}(|V|^3)$.
|
||||
|
||||
In worst case, this is better than the brute force approach.
|
||||
|
||||
### Path Reconstruction
|
||||
|
||||
To reconstruct the path, we have to store the next vertex for each pair and whenever we update the shortest distance we have to update the next vertex as well.
|
||||
|
||||
```c++
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define MAX_DIST 100000000
|
||||
|
||||
|
||||
void Floyd_Warshall(int no_vertices, vector<vector<int> > & distances, vector<vector<int> > & next)
|
||||
{
|
||||
// i shows the phase
|
||||
for(int i = 1; i <= no_vertices; i++)
|
||||
{
|
||||
// Update distance matrix for all pairs
|
||||
for(int a = 1; a <= no_vertices; a++)
|
||||
for(int b = 1; b <= no_vertices; b++)
|
||||
if( distances[a][b] > distances[a][i]+distances[i][b] &&
|
||||
distances[a][i] < MAX_DIST && distances[i][b] < MAX_DIST )
|
||||
{
|
||||
distances[a][b] = distances[a][i]+distances[i][b];
|
||||
next[a][b] = next[a][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
int no_vertices=5;
|
||||
|
||||
// N*N array to store the distances between every pair
|
||||
vector<vector<int> > distances(no_vertices+1, vector<int> (no_vertices+1, MAX_DIST));
|
||||
|
||||
|
||||
// N*N array to store the next vertex for every pair
|
||||
vector<vector<int> > next(no_vertices+1, vector<int> (no_vertices+1, -1));
|
||||
|
||||
|
||||
// Adding the edges virtually by
|
||||
// updating distance matrix and
|
||||
// next vertex matrix
|
||||
distances[1][2]=1, next[1][2] = 2;
|
||||
distances[1][3]=-3, next[1][3] = 3;
|
||||
distances[2][4]=2, next[2][4] = 4;
|
||||
distances[2][5]=1, next[2][5] = 5;
|
||||
distances[3][4]=-1, next[3][4] = 4;
|
||||
distances[3][5]=2, next[3][5] = 5;
|
||||
distances[4][5]=1, next[4][5] = 5;
|
||||
|
||||
// Update all the diagonal elements
|
||||
for(int i = 1; i <= no_vertices; i++)
|
||||
{
|
||||
distances[i][i] = 0;
|
||||
next[i][i] = i;
|
||||
}
|
||||
|
||||
Floyd_Warshall(no_vertices, distances, next);
|
||||
|
||||
// Example of path reconstruction
|
||||
int source = 1, destination = 5;
|
||||
|
||||
while(source != destination)
|
||||
{
|
||||
cout << source << " ";
|
||||
source = next[source][destination];
|
||||
}
|
||||
|
||||
cout << destination << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Negative Cycle Case
|
||||
|
||||
We can use the Floyd-Warshall algorithm to detect the negative cycle and to find the pair of vertices affected by it.
|
||||
|
||||
Initially, the distance between the vertex to itself was zero, but if it turns out to be negative at the end of the algorithm, then there is a negative cycle.
|
||||
|
||||
```c++
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define MAX_DIST 100000000
|
||||
|
||||
|
||||
void Floyd_Warshall_with_NC(int no_vertices, vector<vector<int> > & distances)
|
||||
{
|
||||
// i shows the phase
|
||||
for(int i = 1; i <= no_vertices; i++)
|
||||
for(int a = 1; a <= no_vertices; a++)
|
||||
for(int b = 1; b <= no_vertices; b++)
|
||||
if( distances[a][b] > distances[a][i]+distances[i][b] &&
|
||||
distances[a][i] < MAX_DIST && distances[i][b] < MAX_DIST )
|
||||
distances[a][b] = distances[a][i]+distances[i][b];
|
||||
|
||||
|
||||
bool is_negative_cycle = false;
|
||||
|
||||
// Check for negative cycle
|
||||
for (int i = 1; i <= no_vertices; ++i)
|
||||
for (int a = 1; a <= no_vertices; ++a)
|
||||
for (int b = 1; b <= no_vertices; ++b)
|
||||
{
|
||||
// If there is a negative cycle, then update the distance to -Infinity
|
||||
if (distances[a][i] < MAX_DIST && distances[i][i] < 0
|
||||
&& distances[i][b] < MAX_DIST)
|
||||
{
|
||||
distances[a][b] = -MAX_DIST;
|
||||
is_negative_cycle = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(is_negative_cycle)
|
||||
{
|
||||
cout << "The following pairs are affected by the negative cycle:" << endl;
|
||||
for (int a = 1; a <= no_vertices; ++a)
|
||||
for (int b = 1; b <= no_vertices; ++b)
|
||||
if (distances[a][b] = -MAX_DIST)
|
||||
cout << a << "--" << b << endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int no_vertices=5;
|
||||
|
||||
// N*N array to store the distances between every pair
|
||||
vector<vector<int> > distances(no_vertices+1, vector<int> (no_vertices+1, MAX_DIST));
|
||||
|
||||
|
||||
// Adding the edges virtually by
|
||||
// updating distance matrix
|
||||
distances[1][2]=1;
|
||||
distances[1][3]=-3;
|
||||
distances[2][4]=2;
|
||||
distances[4][1]=1;
|
||||
distances[3][4]=-2;
|
||||
|
||||
for(int i = 1; i <= no_vertices; i++)
|
||||
distances[i][i] = 0;
|
||||
|
||||
Floyd_Warshall_with_NC(no_vertices, distances);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Application of Floyd-Warshall Algorithm
|
||||
|
||||
1. "Widest Path Finding Algorithm", which is an algorithm to finding a path between two vertices of the graph **maximizing the weight of the minimum-weight edge in the path**, can be solved using this algorithm.
|
||||
2. To do optimal routing.
|
||||
3. In Gauss-Jordan Algorithm, to find reduced form of matrix and inversion matrix.
|
||||
|
||||
## Other Shortest Path Finding Algorithms:
|
||||
|
||||
1. Using Dynamic Programming
|
||||
2. Dijkstra's Algorithm
|
||||
3. Bellman-Ford Algorithm
|
175
Akash Articles/Topological-Sort.md
Normal file
175
Akash Articles/Topological-Sort.md
Normal file
@ -0,0 +1,175 @@
|
||||
## Topological Sort of Graph
|
||||
|
||||
Topological Sort is the sorting of the vertices in such a way that, for any two vertices $a$ and $b$, if there is a directed edge from $a \to b$ then $a$ must appear before $b$ in the topological ordering.
|
||||
|
||||
$a,b,c,d,e$ is the topologically sorted order for the graph below.
|
||||
|
||||

|
||||
|
||||
## Quiz Time
|
||||
|
||||
Is it always possible to find out the topological sort?
|
||||
|
||||
No. Whenever there is a cycle in a graph we can not find it.
|
||||
|
||||
To find out the topological sort, we will use the standard graph traversal technique DFS with some modification.
|
||||
|
||||
## Algorithm
|
||||
|
||||
1. Mark all the vertices as unvisited.
|
||||
2. If there is a unvisited vertex, then run the DFS starting from that vertex. Otherwise stop.
|
||||
3. Inside DFS, If all the adjacent vertices of the start vertex are visited, then prepend this vertex at the head of the linked list.
|
||||
4. Go to the step 2.
|
||||
|
||||
Starting from the head, the linked list shows the topological sort of the given graph.
|
||||
|
||||
**Visualization:**
|
||||
|
||||
|
||||
```c++
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define MAX_DIST 100000000
|
||||
|
||||
void dfs(vector<vector<int> > &graph, int start, list<int> &linked_list, vector<bool>& visited)
|
||||
{
|
||||
visited[start] = true;
|
||||
|
||||
for(auto i: graph[start])
|
||||
if(!visited[i])
|
||||
dfs(graph, i, linked_list, visited);
|
||||
|
||||
linked_list.push_front(start);
|
||||
|
||||
}
|
||||
|
||||
void Topological_sort(int no_vertices, vector<vector<int> > &graph)
|
||||
{
|
||||
vector<bool> visited(no_vertices + 1);
|
||||
|
||||
list<int> linked_list;
|
||||
|
||||
for(int i = 1; i <= no_vertices; i++)
|
||||
if(!visited[i])
|
||||
dfs(graph, i, linked_list, visited);
|
||||
|
||||
for(auto vertex: linked_list)
|
||||
cout << vertex << " ";
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
int no_vertices = 5;
|
||||
|
||||
vector<vector<int> > graph(no_vertices+1, vector<int>());
|
||||
|
||||
graph[1].push_back(3);
|
||||
graph[2].push_back(3);
|
||||
graph[3].push_back(4);
|
||||
graph[3].push_back(5);
|
||||
|
||||
Topological_sort(no_vertices, graph);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Quiz Time
|
||||
|
||||
Does topological sort give a unique ordering of the vertices?
|
||||
|
||||
No, it is not unique in every case, because we can find many orderings which satisfies the condition of topological sort.
|
||||
|
||||
In the graph shown in the image above, $b,a,c,d,e$ and $a,b,c,d,e$ both are valid topological sorts.
|
||||
|
||||
## Application
|
||||
|
||||
1. It is used to find out the shortest distance path efficiently.
|
||||
2. Scheduling of tasks according to their dependencies on each other, where dependencies are represented by the directed edges.
|
||||
|
||||
|
||||
## Kahn's Algorithm for Topological Sort
|
||||
|
||||
We have seen how to find the topological sort using modified DFS. Now, we will see Kahn's algorithm, which is modified BFS.
|
||||
|
||||
We will use the indegree of vertices to find the next vertex of the topological ordering. How?
|
||||
|
||||
**The main concept**: If the indegree of the vertex is zero, then it must appear before the vertices whose indegrees are greater than zero.
|
||||
|
||||
## Algorithm
|
||||
|
||||
1. First of all, count the indegrees of all the vertices.
|
||||
2. Add all the vertices whose indegrees are zero to the queue.
|
||||
3. Start the loops like BFS.
|
||||
4. Dequeue a vertex from the queue, say V and append it to the sorting order.
|
||||
5. Visit all the adjacent vertices of V and decrease the indegrees of all of them by 1.
|
||||
6. Enqueue all the adjacent vertices whose indegrees become zero.
|
||||
7. If the queue is empty, then stop the algorithm otherwise continue from the step 4.
|
||||
|
||||
**Visualization**
|
||||
|
||||
```c++
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
#define MAX_DIST 100000000
|
||||
|
||||
|
||||
void Topological_sort(int no_vertices, vector<vector<int> > &graph)
|
||||
{
|
||||
list<int> topological_order;
|
||||
|
||||
vector<int> indegrees(no_vertices + 1);
|
||||
|
||||
for(int i = 1; i <= graph.size(); i++)
|
||||
for(int j = 0; j < graph[j].size(); j++)
|
||||
indegrees[graph[i][j]]++;
|
||||
|
||||
|
||||
queue<int> que;
|
||||
|
||||
for(int i = 1; i <= no_vertices; i++)
|
||||
if(indegrees[i] == 0)
|
||||
que.push(i);
|
||||
|
||||
|
||||
while(!que.empty())
|
||||
{
|
||||
int V = que.front();
|
||||
que.pop();
|
||||
|
||||
topological_order.push_back(V);
|
||||
|
||||
for(auto i: graph[V])
|
||||
{
|
||||
--indegrees[i];
|
||||
if(indegrees[i] == 0)
|
||||
que.push(i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for(auto i: topological_order)
|
||||
cout << i << " ";
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
int no_vertices = 5;
|
||||
|
||||
vector<vector<int> > graph(no_vertices+1, vector<int>());
|
||||
|
||||
graph[1].push_back(3);
|
||||
graph[2].push_back(3);
|
||||
graph[3].push_back(4);
|
||||
graph[3].push_back(5);
|
||||
|
||||
Topological_sort(no_vertices, graph);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
**Variant:** We can use the priority queue in the place of queue if we want smaller indexed vertices to appear first.
|
Loading…
x
Reference in New Issue
Block a user