mirror of
https://hub.njuu.cf/TheAlgorithms/C-Plus-Plus.git
synced 2023-10-11 13:05:55 +08:00
Merge remote-tracking branch 'upstream/fixgraph' into fixgraph
This commit is contained in:
commit
f1b909c8da
@ -39,6 +39,7 @@ add_subdirectory(probability)
|
|||||||
add_subdirectory(data_structures)
|
add_subdirectory(data_structures)
|
||||||
add_subdirectory(machine_learning)
|
add_subdirectory(machine_learning)
|
||||||
add_subdirectory(numerical_methods)
|
add_subdirectory(numerical_methods)
|
||||||
|
add_subdirectory(graph)
|
||||||
|
|
||||||
cmake_policy(SET CMP0054 NEW)
|
cmake_policy(SET CMP0054 NEW)
|
||||||
cmake_policy(SET CMP0057 NEW)
|
cmake_policy(SET CMP0057 NEW)
|
||||||
|
20
graph/CMakeLists.txt
Normal file
20
graph/CMakeLists.txt
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# If necessary, use the RELATIVE flag, otherwise each source file may be listed
|
||||||
|
# with full pathname. RELATIVE may makes it easier to extract an executable name
|
||||||
|
# automatically.
|
||||||
|
file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp )
|
||||||
|
# file( GLOB APP_SOURCES ${CMAKE_SOURCE_DIR}/*.c )
|
||||||
|
# AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_SOURCES)
|
||||||
|
foreach( testsourcefile ${APP_SOURCES} )
|
||||||
|
# I used a simple string replace, to cut off .cpp.
|
||||||
|
string( REPLACE ".cpp" "" testname ${testsourcefile} )
|
||||||
|
add_executable( ${testname} ${testsourcefile} )
|
||||||
|
|
||||||
|
set_target_properties(${testname} PROPERTIES
|
||||||
|
LINKER_LANGUAGE CXX
|
||||||
|
)
|
||||||
|
if(OpenMP_CXX_FOUND)
|
||||||
|
target_link_libraries(${testname} OpenMP::OpenMP_CXX)
|
||||||
|
endif()
|
||||||
|
install(TARGETS ${testname} DESTINATION "bin/graph")
|
||||||
|
|
||||||
|
endforeach( testsourcefile ${APP_SOURCES} )
|
238
graph/bfs.cpp
238
graph/bfs.cpp
@ -1,62 +1,196 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \file
|
||||||
|
* \brief [Breadth First Search Algorithm
|
||||||
|
* (Breadth First Search)](https://en.wikipedia.org/wiki/Breadth-first_search)
|
||||||
|
*
|
||||||
|
* \author [Ayaan Khan](http://github.com/ayaankhan98)
|
||||||
|
*
|
||||||
|
* \details
|
||||||
|
* Breadth First Search also quoted as BFS is a Graph Traversal Algorithm.
|
||||||
|
* Time Complexity O(|V| + |E|) where V are the number of vertices and E
|
||||||
|
* are the number of edges in the graph.
|
||||||
|
*
|
||||||
|
* Applications of Breadth First Search are
|
||||||
|
*
|
||||||
|
* 1. Finding shortest path between two vertices say u and v, with path
|
||||||
|
* length measured by number of edges (an advantage over depth first
|
||||||
|
* search algorithm)
|
||||||
|
* 2. Ford-Fulkerson Method for computing the maximum flow in a flow network.
|
||||||
|
* 3. Testing bipartiteness of a graph.
|
||||||
|
* 4. Cheney's Algorithm, Copying garbage collection.
|
||||||
|
*
|
||||||
|
* And there are many more...
|
||||||
|
*
|
||||||
|
* <h4>working</h4>
|
||||||
|
* In the implementation below we first created a graph using the adjacency
|
||||||
|
* list representation of graph.
|
||||||
|
* Breadth First Search Works as follows
|
||||||
|
* it requires a vertex as a start vertex, Start vertex is that vertex
|
||||||
|
* from where you want to start traversing the graph.
|
||||||
|
* we maintain a bool array or a vector to keep track of the vertices
|
||||||
|
* which we have visited so that we do not traverse the visited vertices
|
||||||
|
* again and again and eventually fall into an infinite loop. Along with this
|
||||||
|
* boolen array we use a Queue.
|
||||||
|
*
|
||||||
|
* 1. First we mark the start vertex as visited.
|
||||||
|
* 2. Push this visited vertex in the Queue.
|
||||||
|
* 3. while the queue is not empty we repeat the following steps
|
||||||
|
*
|
||||||
|
* 1. Take out an element from the front of queue
|
||||||
|
* 2. start exploring the adjacency list of this vertex
|
||||||
|
* if element in the adjacency list is not visited then we
|
||||||
|
* push that element into the queue and mark this as visited
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
using namespace std;
|
#include <queue>
|
||||||
class graph {
|
#include <vector>
|
||||||
int v;
|
|
||||||
list<int> *adj;
|
|
||||||
|
|
||||||
public:
|
/**
|
||||||
graph(int v);
|
* \namespace graph
|
||||||
void addedge(int src, int dest);
|
* \brief Graph algorithms
|
||||||
void printgraph();
|
*/
|
||||||
void bfs(int s);
|
namespace graph {
|
||||||
};
|
/**
|
||||||
graph::graph(int v) {
|
* \brief
|
||||||
this->v = v;
|
* Adds and edge between two vertices of graph say u and v in this
|
||||||
this->adj = new list<int>[v];
|
* case.
|
||||||
|
*
|
||||||
|
* @param adj Adjacency list representation of graph
|
||||||
|
* @param u first vertex
|
||||||
|
* @param v second vertex
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void addEdge(std::vector<std::vector<int>> *adj, int u, int v) {
|
||||||
|
/**
|
||||||
|
* Here we are considering directed graph that's the
|
||||||
|
* reason we are adding v to the adjacency list representation of u
|
||||||
|
* but not adding u to the adjacency list representation of v
|
||||||
|
*
|
||||||
|
* in case of a un-directed graph you can un comment the statement below.
|
||||||
|
*/
|
||||||
|
(*adj)[u - 1].push_back(v - 1);
|
||||||
|
// adj[v - 1].push_back(u -1);
|
||||||
}
|
}
|
||||||
void graph::addedge(int src, int dest) {
|
|
||||||
src--;
|
/**
|
||||||
dest--;
|
* \brief
|
||||||
adj[src].push_back(dest);
|
* Function performs the breadth first search algorithm over the graph
|
||||||
// adj[dest].push_back(src);
|
*
|
||||||
}
|
* @param adj Adjacency list representation of graph
|
||||||
void graph::printgraph() {
|
* @param start vertex from where traversing starts
|
||||||
for (int i = 0; i < this->v; i++) {
|
*
|
||||||
cout << "Adjacency list of vertex " << i + 1 << " is \n";
|
*/
|
||||||
list<int>::iterator it;
|
std::vector<int> beadth_first_search(const std::vector<std::vector<int>> &adj,
|
||||||
for (it = adj[i].begin(); it != adj[i].end(); ++it) {
|
int start) {
|
||||||
cout << *it + 1 << " ";
|
size_t vertices = adj.size();
|
||||||
}
|
|
||||||
cout << endl;
|
std::vector<int> result;
|
||||||
}
|
|
||||||
}
|
/// vector to keep track of visited vertices
|
||||||
void graph::bfs(int s) {
|
std::vector<bool> visited(vertices, 0);
|
||||||
bool *visited = new bool[this->v + 1];
|
|
||||||
memset(visited, false, sizeof(bool) * (this->v + 1));
|
std::queue<int> tracker;
|
||||||
visited[s] = true;
|
/// marking the start vertex as visited
|
||||||
list<int> q;
|
visited[start] = true;
|
||||||
q.push_back(s);
|
tracker.push(start);
|
||||||
list<int>::iterator it;
|
while (!tracker.empty()) {
|
||||||
while (!q.empty()) {
|
size_t vertex = tracker.front();
|
||||||
int u = q.front();
|
tracker.pop();
|
||||||
cout << u << " ";
|
result.push_back(vertex + 1);
|
||||||
q.pop_front();
|
for (auto x : adj[vertex]) {
|
||||||
for (it = adj[u].begin(); it != adj[u].end(); ++it) {
|
/// if the vertex is not visited then mark this as visited
|
||||||
if (visited[*it] == false) {
|
/// and push it to the queue
|
||||||
visited[*it] = true;
|
if (!visited[x]) {
|
||||||
q.push_back(*it);
|
visited[x] = true;
|
||||||
|
tracker.push(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
} // namespace graph
|
||||||
|
|
||||||
|
void tests() {
|
||||||
|
std::cout << "Initiating Tests" << std::endl;
|
||||||
|
|
||||||
|
/// Test 1 Begin
|
||||||
|
std::vector<std::vector<int>> graphData(4, std::vector<int>());
|
||||||
|
graph::addEdge(&graphData, 1, 2);
|
||||||
|
graph::addEdge(&graphData, 1, 3);
|
||||||
|
graph::addEdge(&graphData, 2, 3);
|
||||||
|
graph::addEdge(&graphData, 3, 1);
|
||||||
|
graph::addEdge(&graphData, 3, 4);
|
||||||
|
graph::addEdge(&graphData, 4, 4);
|
||||||
|
|
||||||
|
std::vector<int> returnedResult = graph::beadth_first_search(graphData, 2);
|
||||||
|
std::vector<int> correctResult = {3, 1, 4, 2};
|
||||||
|
|
||||||
|
assert(std::equal(correctResult.begin(), correctResult.end(),
|
||||||
|
returnedResult.begin()));
|
||||||
|
std::cout << "Test 1 Passed..." << std::endl;
|
||||||
|
|
||||||
|
/// Test 2 Begin
|
||||||
|
/// clear data from previous test
|
||||||
|
returnedResult.clear();
|
||||||
|
correctResult.clear();
|
||||||
|
|
||||||
|
returnedResult = graph::beadth_first_search(graphData, 0);
|
||||||
|
correctResult = {1, 2, 3, 4};
|
||||||
|
|
||||||
|
assert(std::equal(correctResult.begin(), correctResult.end(),
|
||||||
|
returnedResult.begin()));
|
||||||
|
std::cout << "Test 2 Passed..." << std::endl;
|
||||||
|
|
||||||
|
/// Test 3 Begins
|
||||||
|
/// clear data from previous test
|
||||||
|
graphData.clear();
|
||||||
|
returnedResult.clear();
|
||||||
|
correctResult.clear();
|
||||||
|
|
||||||
|
graphData.resize(6);
|
||||||
|
graph::addEdge(&graphData, 1, 2);
|
||||||
|
graph::addEdge(&graphData, 1, 3);
|
||||||
|
graph::addEdge(&graphData, 2, 4);
|
||||||
|
graph::addEdge(&graphData, 3, 4);
|
||||||
|
graph::addEdge(&graphData, 2, 5);
|
||||||
|
graph::addEdge(&graphData, 4, 6);
|
||||||
|
|
||||||
|
returnedResult = graph::beadth_first_search(graphData, 0);
|
||||||
|
correctResult = {1, 2, 3, 4, 5, 6};
|
||||||
|
|
||||||
|
assert(std::equal(correctResult.begin(), correctResult.end(),
|
||||||
|
returnedResult.begin()));
|
||||||
|
std::cout << "Test 3 Passed..." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Main function */
|
||||||
int main() {
|
int main() {
|
||||||
graph g(4);
|
/// running predefined test cases
|
||||||
g.addedge(1, 2);
|
tests();
|
||||||
g.addedge(2, 3);
|
|
||||||
g.addedge(3, 4);
|
size_t vertices, edges;
|
||||||
g.addedge(1, 4);
|
std::cout << "Enter the number of vertices : ";
|
||||||
g.addedge(1, 3);
|
std::cin >> vertices;
|
||||||
// g.printgraph();
|
std::cout << "Enter the number of edges : ";
|
||||||
g.bfs(2);
|
std::cin >> edges;
|
||||||
|
|
||||||
|
/// creating a graph
|
||||||
|
std::vector<std::vector<int>> adj(vertices, std::vector<int>());
|
||||||
|
|
||||||
|
/// taking input for edges
|
||||||
|
std::cout << "Enter vertices in pair which have edges between them : "
|
||||||
|
<< std::endl;
|
||||||
|
while (edges--) {
|
||||||
|
int u, v;
|
||||||
|
std::cin >> u >> v;
|
||||||
|
graph::addEdge(&adj, u, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// running Breadth First Search Algorithm on the graph
|
||||||
|
graph::beadth_first_search(adj, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -7,9 +7,11 @@
|
|||||||
#include <algorithm> // for min & max
|
#include <algorithm> // for min & max
|
||||||
#include <iostream> // for cout
|
#include <iostream> // for cout
|
||||||
#include <vector> // for std::vector
|
#include <vector> // for std::vector
|
||||||
|
|
||||||
using std::cout;
|
using std::cout;
|
||||||
using std::min;
|
using std::min;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
class Solution {
|
class Solution {
|
||||||
vector<vector<int>> graph;
|
vector<vector<int>> graph;
|
||||||
vector<int> in_time, out_time;
|
vector<int> in_time, out_time;
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
* <pre>
|
* <pre>
|
||||||
* Example - Here is graph with 3 connected components
|
* Example - Here is graph with 3 connected components
|
||||||
*
|
*
|
||||||
* 3 9 6 8
|
* 1 4 5 8
|
||||||
* / \ / / \ / \
|
* / \ / / \ / \
|
||||||
* 2---4 2 7 3 7
|
* 2---3 6 7 9 10
|
||||||
*
|
*
|
||||||
* first second third
|
* first second third
|
||||||
* component component component
|
* component component component
|
||||||
@ -26,97 +26,123 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
using std::vector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for representing graph as a adjacency list.
|
* @namespace graph
|
||||||
|
* @brief Graph Algorithms
|
||||||
*/
|
*/
|
||||||
class graph {
|
|
||||||
private:
|
|
||||||
/** \brief adj stores adjacency list representation of graph */
|
|
||||||
vector<vector<int>> adj;
|
|
||||||
|
|
||||||
/** \brief keep track of connected components */
|
|
||||||
int connected_components;
|
|
||||||
|
|
||||||
void depth_first_search();
|
|
||||||
void explore(int, vector<bool> &);
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* \brief Constructor that intiliazes the graph on creation and set
|
|
||||||
* the connected components to 0
|
|
||||||
*/
|
|
||||||
explicit graph(int n) : adj(n, vector<int>()) { connected_components = 0; }
|
|
||||||
|
|
||||||
void addEdge(int, int);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Function the calculates the connected compoents in the graph
|
|
||||||
* by performing the depth first search on graph
|
|
||||||
*
|
|
||||||
* @return connected_components total connected components in graph
|
|
||||||
*/
|
|
||||||
int getConnectedComponents() {
|
|
||||||
depth_first_search();
|
|
||||||
return connected_components;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
namespace graph {
|
||||||
/**
|
/**
|
||||||
* \brief Function that add edge between two nodes or vertices of graph
|
* @brief Function that add edge between two nodes or vertices of graph
|
||||||
*
|
*
|
||||||
* @param u any node or vertex of graph
|
* @param adj adjacency list of graph.
|
||||||
* @param v any node or vertex of graph
|
* @param u any node or vertex of graph.
|
||||||
|
* @param v any node or vertex of graph.
|
||||||
*/
|
*/
|
||||||
void graph::addEdge(int u, int v) {
|
void addEdge(std::vector<std::vector<int>> *adj, int u, int v) {
|
||||||
adj[u - 1].push_back(v - 1);
|
(*adj)[u - 1].push_back(v - 1);
|
||||||
adj[v - 1].push_back(u - 1);
|
(*adj)[v - 1].push_back(u - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Function that perfoms depth first search algorithm on graph
|
* @brief Utility function for depth first seach algorithm
|
||||||
|
* this function explores the vertex which is passed into.
|
||||||
|
*
|
||||||
|
* @param adj adjacency list of graph.
|
||||||
|
* @param u vertex or node to be explored.
|
||||||
|
* @param visited already visited vertices.
|
||||||
*/
|
*/
|
||||||
void graph::depth_first_search() {
|
void explore(const std::vector<std::vector<int>> *adj, int u,
|
||||||
int n = adj.size();
|
std::vector<bool> *visited) {
|
||||||
vector<bool> visited(n, false);
|
(*visited)[u] = true;
|
||||||
|
for (auto v : (*adj)[u]) {
|
||||||
|
if (!(*visited)[v]) {
|
||||||
|
explore(adj, v, visited);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function that perfoms depth first search algorithm on graph
|
||||||
|
* and calculated the number of connected components.
|
||||||
|
*
|
||||||
|
* @param adj adjacency list of graph.
|
||||||
|
*
|
||||||
|
* @return connected_components number of connected components in graph.
|
||||||
|
*/
|
||||||
|
int getConnectedComponents(const std::vector<std::vector<int>> *adj) {
|
||||||
|
int n = adj->size();
|
||||||
|
int connected_components = 0;
|
||||||
|
std::vector<bool> visited(n, false);
|
||||||
|
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
if (!visited[i]) {
|
if (!visited[i]) {
|
||||||
explore(i, visited);
|
explore(adj, i, &visited);
|
||||||
connected_components++;
|
connected_components++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return connected_components;
|
||||||
}
|
}
|
||||||
/**
|
} // namespace graph
|
||||||
* \brief Utility function for depth first seach algorithm
|
|
||||||
* this function explores the vertex which is passed into.
|
/** Function to test the algorithm */
|
||||||
*
|
void tests() {
|
||||||
* @param u vertex or node to be explored
|
std::cout << "Running predefined tests..." << std::endl;
|
||||||
* @param visited already visited vertex
|
std::cout << "Initiating Test 1..." << std::endl;
|
||||||
*/
|
std::vector<std::vector<int>> adj1(9, std::vector<int>());
|
||||||
void graph::explore(int u, vector<bool> &visited) {
|
graph::addEdge(&adj1, 1, 2);
|
||||||
visited[u] = true;
|
graph::addEdge(&adj1, 1, 3);
|
||||||
for (auto v : adj[u]) {
|
graph::addEdge(&adj1, 3, 4);
|
||||||
if (!visited[v]) {
|
graph::addEdge(&adj1, 5, 7);
|
||||||
explore(v, visited);
|
graph::addEdge(&adj1, 5, 6);
|
||||||
}
|
graph::addEdge(&adj1, 8, 9);
|
||||||
}
|
|
||||||
|
assert(graph::getConnectedComponents(&adj1) == 3);
|
||||||
|
std::cout << "Test 1 Passed..." << std::endl;
|
||||||
|
|
||||||
|
std::cout << "Innitiating Test 2..." << std::endl;
|
||||||
|
std::vector<std::vector<int>> adj2(10, std::vector<int>());
|
||||||
|
graph::addEdge(&adj2, 1, 2);
|
||||||
|
graph::addEdge(&adj2, 1, 3);
|
||||||
|
graph::addEdge(&adj2, 1, 4);
|
||||||
|
graph::addEdge(&adj2, 2, 3);
|
||||||
|
graph::addEdge(&adj2, 3, 4);
|
||||||
|
graph::addEdge(&adj2, 4, 8);
|
||||||
|
graph::addEdge(&adj2, 4, 10);
|
||||||
|
graph::addEdge(&adj2, 8, 10);
|
||||||
|
graph::addEdge(&adj2, 8, 9);
|
||||||
|
graph::addEdge(&adj2, 5, 7);
|
||||||
|
graph::addEdge(&adj2, 5, 6);
|
||||||
|
graph::addEdge(&adj2, 6, 7);
|
||||||
|
|
||||||
|
assert(graph::getConnectedComponents(&adj2) == 2);
|
||||||
|
std::cout << "Test 2 Passed..." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Main function */
|
/** Main function */
|
||||||
int main() {
|
int main() {
|
||||||
/// creating a graph with 4 vertex
|
/// running predefined tests
|
||||||
graph g(4);
|
tests();
|
||||||
|
|
||||||
/// Adding edges between vertices
|
int vertices = int(), edges = int();
|
||||||
g.addEdge(1, 2);
|
std::cout << "Enter the number of vertices : ";
|
||||||
g.addEdge(3, 2);
|
std::cin >> vertices;
|
||||||
|
std::cout << "Enter the number of edges : ";
|
||||||
|
std::cin >> edges;
|
||||||
|
|
||||||
/// printing the connected components
|
std::vector<std::vector<int>> adj(vertices, std::vector<int>());
|
||||||
std::cout << g.getConnectedComponents();
|
|
||||||
|
int u = int(), v = int();
|
||||||
|
while (edges--) {
|
||||||
|
std::cin >> u >> v;
|
||||||
|
graph::addEdge(&adj, u, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cc = graph::getConnectedComponents(&adj);
|
||||||
|
std::cout << cc << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,313 +1,57 @@
|
|||||||
/**
|
#include <iostream>
|
||||||
* @file cycle_check_directed graph.cpp
|
#include <vector>
|
||||||
*
|
#include <stdlib.h>
|
||||||
* @brief BFS and DFS algorithms to check for cycle in a directed graph.
|
using std::vector;
|
||||||
*
|
using std::pair;
|
||||||
* @author [Anmol3299](mailto:mittalanmol22@gmail.com)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <iostream> // for std::cout
|
void explore(int i, vector<vector<int>> &adj, int *state)
|
||||||
#include <map> // for std::map
|
{
|
||||||
#include <queue> // for std::queue
|
state[i] = 1;
|
||||||
#include <stdexcept> // for throwing errors
|
for(auto it2 : adj[i])
|
||||||
#include <type_traits> // for std::remove_reference
|
{
|
||||||
#include <utility> // for std::move
|
if (state[it2] == 0)
|
||||||
#include <vector> // for std::vector
|
{
|
||||||
|
explore(it2, adj,state);
|
||||||
/**
|
}
|
||||||
* Implementation of non-weighted directed edge of a graph.
|
if (state[it2] == 1)
|
||||||
*
|
{
|
||||||
* The source vertex of the edge is labelled "src" and destination vertex is
|
std::cout<<"1";
|
||||||
* labelled "dest".
|
exit(0);
|
||||||
*/
|
}
|
||||||
struct Edge {
|
}
|
||||||
unsigned int src;
|
state[i] = 2;
|
||||||
unsigned int dest;
|
|
||||||
|
|
||||||
Edge() = delete;
|
|
||||||
~Edge() = default;
|
|
||||||
Edge(Edge&&) = default;
|
|
||||||
Edge& operator=(Edge&&) = default;
|
|
||||||
Edge(Edge const&) = default;
|
|
||||||
Edge& operator=(Edge const&) = default;
|
|
||||||
|
|
||||||
/** Set the source and destination of the vertex.
|
|
||||||
*
|
|
||||||
* @param source is the source vertex of the edge.
|
|
||||||
* @param destination is the destination vertex of the edge.
|
|
||||||
*/
|
|
||||||
Edge(unsigned int source, unsigned int destination)
|
|
||||||
: src(source), dest(destination) {}
|
|
||||||
};
|
};
|
||||||
|
int acyclic(vector<vector<int> > &adj,size_t n) {
|
||||||
|
//write your code here
|
||||||
|
|
||||||
using AdjList = std::map<unsigned int, std::vector<unsigned int>>;
|
int state[n]; // permitted states are 0 1 and 2
|
||||||
|
|
||||||
/**
|
// mark the states of all vertices initially to 0
|
||||||
* Implementation of graph class.
|
for(int i=0;i<n;i++)
|
||||||
*
|
state[i] = 0;
|
||||||
* The graph will be represented using Adjacency List representation.
|
|
||||||
* This class contains 2 data members "m_vertices" & "m_adjList" used to
|
|
||||||
* represent the number of vertices and adjacency list of the graph
|
|
||||||
* respectively. The vertices are labelled 0 - (m_vertices - 1).
|
|
||||||
*/
|
|
||||||
class Graph {
|
|
||||||
public:
|
|
||||||
Graph() : m_vertices(0), m_adjList({}) {}
|
|
||||||
~Graph() = default;
|
|
||||||
Graph(Graph&&) = default;
|
|
||||||
Graph& operator=(Graph&&) = default;
|
|
||||||
Graph(Graph const&) = default;
|
|
||||||
Graph& operator=(Graph const&) = default;
|
|
||||||
|
|
||||||
/** Create a graph from vertices and adjacency list.
|
for(auto it1 = 0; it1 != adj.size(); it1++)
|
||||||
*
|
{
|
||||||
* @param vertices specify the number of vertices the graph would contain.
|
if (state[it1] == 0)
|
||||||
* @param adjList is the adjacency list representation of graph.
|
explore(it1,adj,state);
|
||||||
*/
|
if (state[it1] == 1)
|
||||||
Graph(unsigned int vertices, AdjList const& adjList)
|
{
|
||||||
: m_vertices(vertices), m_adjList(adjList) {}
|
std::cout<<"1";
|
||||||
|
exit(0);
|
||||||
/** Create a graph from vertices and adjacency list.
|
|
||||||
*
|
|
||||||
* @param vertices specify the number of vertices the graph would contain.
|
|
||||||
* @param adjList is the adjacency list representation of graph.
|
|
||||||
*/
|
|
||||||
Graph(unsigned int vertices, AdjList&& adjList)
|
|
||||||
: m_vertices(vertices), m_adjList(std::move(adjList)) {}
|
|
||||||
|
|
||||||
/** Create a graph from vertices and a set of edges.
|
|
||||||
*
|
|
||||||
* Adjacency list of the graph would be created from the set of edges. If
|
|
||||||
* the source or destination of any edge has a value greater or equal to
|
|
||||||
* number of vertices, then it would throw a range_error.
|
|
||||||
*
|
|
||||||
* @param vertices specify the number of vertices the graph would contain.
|
|
||||||
* @param edges is a vector of edges.
|
|
||||||
*/
|
|
||||||
Graph(unsigned int vertices, std::vector<Edge> const& edges)
|
|
||||||
: m_vertices(vertices) {
|
|
||||||
for (auto const& edge : edges) {
|
|
||||||
if (edge.src >= vertices || edge.dest >= vertices) {
|
|
||||||
throw std::range_error(
|
|
||||||
"Either src or dest of edge out of range");
|
|
||||||
}
|
|
||||||
m_adjList[edge.src].emplace_back(edge.dest);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/** Return a const reference of the adjacency list.
|
std::cout<<"0";
|
||||||
*
|
return 0;
|
||||||
* @return const reference to the adjacency list
|
}
|
||||||
*/
|
|
||||||
std::remove_reference<AdjList>::type const& getAdjList() const {
|
int main() {
|
||||||
return m_adjList;
|
size_t n, m;
|
||||||
}
|
std::cin >> n >> m;
|
||||||
|
vector<vector<int> > adj(n, vector<int>());
|
||||||
/**
|
for (size_t i = 0; i < m; i++) {
|
||||||
* @return number of vertices in the graph.
|
int x, y;
|
||||||
*/
|
std::cin >> x >> y;
|
||||||
unsigned int getVertices() const { return m_vertices; }
|
adj[x - 1].push_back(y - 1);
|
||||||
|
}
|
||||||
/** Add vertices in the graph.
|
acyclic(adj,n);
|
||||||
*
|
|
||||||
* @param num is the number of vertices to be added. It adds 1 vertex by
|
|
||||||
* default.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void addVertices(unsigned int num = 1) { m_vertices += num; }
|
|
||||||
|
|
||||||
/** Add an edge in the graph.
|
|
||||||
*
|
|
||||||
* @param edge that needs to be added.
|
|
||||||
*/
|
|
||||||
void addEdge(Edge const& edge) {
|
|
||||||
if (edge.src >= m_vertices || edge.dest >= m_vertices) {
|
|
||||||
throw std::range_error("Either src or dest of edge out of range");
|
|
||||||
}
|
|
||||||
m_adjList[edge.src].emplace_back(edge.dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add an Edge in the graph
|
|
||||||
*
|
|
||||||
* @param source is source vertex of the edge.
|
|
||||||
* @param destination is the destination vertex of the edge.
|
|
||||||
*/
|
|
||||||
void addEdge(unsigned int source, unsigned int destination) {
|
|
||||||
if (source >= m_vertices || destination >= m_vertices) {
|
|
||||||
throw std::range_error(
|
|
||||||
"Either source or destination of edge out of range");
|
|
||||||
}
|
|
||||||
m_adjList[source].emplace_back(destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned int m_vertices;
|
|
||||||
AdjList m_adjList;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a directed graph has a cycle or not.
|
|
||||||
*
|
|
||||||
* This class provides 2 methods to check for cycle in a directed graph:
|
|
||||||
* isCyclicDFS & isCyclicBFS.
|
|
||||||
*
|
|
||||||
* - isCyclicDFS uses DFS traversal method to check for cycle in a graph.
|
|
||||||
* - isCyclidBFS used BFS traversal method to check for cycle in a graph.
|
|
||||||
*/
|
|
||||||
class CycleCheck {
|
|
||||||
private:
|
|
||||||
enum nodeStates : uint8_t { not_visited = 0, in_stack, visited };
|
|
||||||
|
|
||||||
/** Helper function of "isCyclicDFS".
|
|
||||||
*
|
|
||||||
* @param adjList is the adjacency list representation of some graph.
|
|
||||||
* @param state is the state of the nodes of the graph.
|
|
||||||
* @param node is the node being evaluated.
|
|
||||||
*
|
|
||||||
* @return true if graph has a cycle, else false.
|
|
||||||
*/
|
|
||||||
static bool isCyclicDFSHelper(AdjList const& adjList,
|
|
||||||
std::vector<nodeStates>* state,
|
|
||||||
unsigned int node) {
|
|
||||||
// Add node "in_stack" state.
|
|
||||||
(*state)[node] = in_stack;
|
|
||||||
|
|
||||||
// If the node has children, then recursively visit all children of the
|
|
||||||
// node.
|
|
||||||
auto const it = adjList.find(node);
|
|
||||||
if (it != adjList.end()) {
|
|
||||||
for (auto child : it->second) {
|
|
||||||
// If state of child node is "not_visited", evaluate that child
|
|
||||||
// for presence of cycle.
|
|
||||||
auto state_of_child = (*state)[child];
|
|
||||||
if (state_of_child == not_visited) {
|
|
||||||
if (isCyclicDFSHelper(adjList, state, child)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (state_of_child == in_stack) {
|
|
||||||
// If child node was "in_stack", then that means that there
|
|
||||||
// is a cycle in the graph. Return true for presence of the
|
|
||||||
// cycle.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Current node has been evaluated for the presence of cycle and had no
|
|
||||||
// cycle. Mark current node as "visited".
|
|
||||||
(*state)[node] = visited;
|
|
||||||
// Return that current node didn't result in any cycles.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** Driver function to check if a graph has a cycle.
|
|
||||||
*
|
|
||||||
* This function uses DFS to check for cycle in the graph.
|
|
||||||
*
|
|
||||||
* @param graph which needs to be evaluated for the presence of cycle.
|
|
||||||
* @return true if a cycle is detected, else false.
|
|
||||||
*/
|
|
||||||
static bool isCyclicDFS(Graph const& graph) {
|
|
||||||
auto vertices = graph.getVertices();
|
|
||||||
|
|
||||||
/** State of the node.
|
|
||||||
*
|
|
||||||
* It is a vector of "nodeStates" which represents the state node is in.
|
|
||||||
* It can take only 3 values: "not_visited", "in_stack", and "visited".
|
|
||||||
*
|
|
||||||
* Initially, all nodes are in "not_visited" state.
|
|
||||||
*/
|
|
||||||
std::vector<nodeStates> state(vertices, not_visited);
|
|
||||||
|
|
||||||
// Start visiting each node.
|
|
||||||
for (unsigned int node = 0; node < vertices; node++) {
|
|
||||||
// If a node is not visited, only then check for presence of cycle.
|
|
||||||
// There is no need to check for presence of cycle for a visited
|
|
||||||
// node as it has already been checked for presence of cycle.
|
|
||||||
if (state[node] == not_visited) {
|
|
||||||
// Check for cycle.
|
|
||||||
if (isCyclicDFSHelper(graph.getAdjList(), &state, node)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// All nodes have been safely traversed, that means there is no cycle in
|
|
||||||
// the graph. Return false.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Check if a graph has cycle or not.
|
|
||||||
*
|
|
||||||
* This function uses BFS to check if a graph is cyclic or not.
|
|
||||||
*
|
|
||||||
* @param graph which needs to be evaluated for the presence of cycle.
|
|
||||||
* @return true if a cycle is detected, else false.
|
|
||||||
*/
|
|
||||||
static bool isCyclicBFS(Graph const& graph) {
|
|
||||||
auto graphAjdList = graph.getAdjList();
|
|
||||||
auto vertices = graph.getVertices();
|
|
||||||
|
|
||||||
std::vector<unsigned int> indegree(vertices, 0);
|
|
||||||
// Calculate the indegree i.e. the number of incident edges to the node.
|
|
||||||
for (auto const& list : graphAjdList) {
|
|
||||||
auto children = list.second;
|
|
||||||
for (auto const& child : children) {
|
|
||||||
indegree[child]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::queue<unsigned int> can_be_solved;
|
|
||||||
for (unsigned int node = 0; node < vertices; node++) {
|
|
||||||
// If a node doesn't have any input edges, then that node will
|
|
||||||
// definately not result in a cycle and can be visited safely.
|
|
||||||
if (!indegree[node]) {
|
|
||||||
can_be_solved.emplace(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vertices that need to be traversed.
|
|
||||||
auto remain = vertices;
|
|
||||||
// While there are safe nodes that we can visit.
|
|
||||||
while (!can_be_solved.empty()) {
|
|
||||||
auto solved = can_be_solved.front();
|
|
||||||
// Visit the node.
|
|
||||||
can_be_solved.pop();
|
|
||||||
// Decrease number of nodes that need to be traversed.
|
|
||||||
remain--;
|
|
||||||
|
|
||||||
// Visit all the children of the visited node.
|
|
||||||
auto it = graphAjdList.find(solved);
|
|
||||||
if (it != graphAjdList.end()) {
|
|
||||||
for (auto child : it->second) {
|
|
||||||
// Check if we can visited the node safely.
|
|
||||||
if (--indegree[child] == 0) {
|
|
||||||
// if node can be visited safely, then add that node to
|
|
||||||
// the visit queue.
|
|
||||||
can_be_solved.emplace(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are still nodes that we can't visit, then it means that
|
|
||||||
// there is a cycle and return true, else return false.
|
|
||||||
return !(remain == 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main function.
|
|
||||||
*/
|
|
||||||
int main() {
|
|
||||||
// Instantiate the graph.
|
|
||||||
Graph g(7, std::vector<Edge>{{0, 1}, {1, 2}, {2, 0}, {2, 5}, {3, 5}});
|
|
||||||
// Check for cycle using BFS method.
|
|
||||||
std::cout << CycleCheck::isCyclicBFS(g) << '\n';
|
|
||||||
|
|
||||||
// Check for cycle using DFS method.
|
|
||||||
std::cout << CycleCheck::isCyclicDFS(g) << '\n';
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
141
graph/dfs.cpp
141
graph/dfs.cpp
@ -1,26 +1,133 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \file
|
||||||
|
* \brief [Depth First Search Algorithm
|
||||||
|
* (Depth First Search)](https://en.wikipedia.org/wiki/Depth-first_search)
|
||||||
|
*
|
||||||
|
* \author [Ayaan Khan](http://github.com/ayaankhan98)
|
||||||
|
*
|
||||||
|
* \details
|
||||||
|
* Depth First Search also quoted as DFS is a Graph Traversal Algorithm.
|
||||||
|
* Time Complexity O(|V| + |E|) where V is number of vertices and E
|
||||||
|
* is number of edges in graph.
|
||||||
|
*
|
||||||
|
* Application of Depth First Search are
|
||||||
|
*
|
||||||
|
* 1. Finding connected components
|
||||||
|
* 2. Finding 2-(edge or vertex)-connected components.
|
||||||
|
* 3. Finding 3-(edge or vertex)-connected components.
|
||||||
|
* 4. Finding the bridges of a graph.
|
||||||
|
* 5. Generating words in order to plot the limit set of a group.
|
||||||
|
* 6. Finding strongly connected components.
|
||||||
|
*
|
||||||
|
* And there are many more...
|
||||||
|
*
|
||||||
|
* <h4>Working</h4>
|
||||||
|
* 1. Mark all vertices as unvisited first
|
||||||
|
* 2. start exploring from some starting vertex.
|
||||||
|
*
|
||||||
|
* While exploring vertex we mark the vertex as visited
|
||||||
|
* and start exploring the vertices connected to this
|
||||||
|
* vertex in recursive way.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
using namespace std;
|
#include <vector>
|
||||||
int v = 4;
|
|
||||||
void DFSUtil_(int graph[4][4], bool visited[], int s) {
|
/**
|
||||||
visited[s] = true;
|
*
|
||||||
cout << s << " ";
|
* \namespace graph
|
||||||
for (int i = 0; i < v; i++) {
|
* \brief Graph Algorithms
|
||||||
if (graph[s][i] == 1 && visited[i] == false) {
|
*
|
||||||
DFSUtil_(graph, visited, i);
|
*/
|
||||||
|
namespace graph {
|
||||||
|
/**
|
||||||
|
* \brief
|
||||||
|
* Adds and edge between two vertices of graph say u and v in this
|
||||||
|
* case.
|
||||||
|
*
|
||||||
|
* @param adj Adjacency list representation of graph
|
||||||
|
* @param u first vertex
|
||||||
|
* @param v second vertex
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void addEdge(std::vector<std::vector<size_t>> *adj, size_t u, size_t v) {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Here we are considering undirected graph that's the
|
||||||
|
* reason we are adding v to the adjacency list representation of u
|
||||||
|
* and also adding u to the adjacency list representation of v
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
(*adj)[u - 1].push_back(v - 1);
|
||||||
|
(*adj)[v - 1].push_back(u - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* \brief
|
||||||
|
* Explores the given vertex, exploring a vertex means traversing
|
||||||
|
* over all the vertices which are connected to the vertex that is
|
||||||
|
* currently being explored.
|
||||||
|
*
|
||||||
|
* @param adj garph
|
||||||
|
* @param v vertex to be explored
|
||||||
|
* @param visited already visited vertices
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void explore(const std::vector<std::vector<size_t>> &adj, size_t v,
|
||||||
|
std::vector<bool> *visited) {
|
||||||
|
std::cout << v + 1 << " ";
|
||||||
|
(*visited)[v] = true;
|
||||||
|
for (auto x : adj[v]) {
|
||||||
|
if (!(*visited)[x]) {
|
||||||
|
explore(adj, x, visited);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DFS_(int graph[4][4], int s) {
|
/**
|
||||||
bool visited[v];
|
* \brief
|
||||||
memset(visited, 0, sizeof(visited));
|
* initiates depth first search algorithm.
|
||||||
DFSUtil_(graph, visited, s);
|
*
|
||||||
}
|
* @param adj adjacency list of graph
|
||||||
|
* @param start vertex from where DFS starts traversing.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void depth_first_search(const std::vector<std::vector<size_t>> &adj,
|
||||||
|
size_t start) {
|
||||||
|
size_t vertices = adj.size();
|
||||||
|
|
||||||
|
std::vector<bool> visited(vertices, false);
|
||||||
|
explore(adj, start, &visited);
|
||||||
|
}
|
||||||
|
} // namespace graph
|
||||||
|
|
||||||
|
/** Main function */
|
||||||
int main() {
|
int main() {
|
||||||
int graph[4][4] = {{0, 1, 1, 0}, {0, 0, 1, 0}, {1, 0, 0, 1}, {0, 0, 0, 1}};
|
size_t vertices, edges;
|
||||||
cout << "DFS: ";
|
std::cout << "Enter the Vertices : ";
|
||||||
DFS_(graph, 2);
|
std::cin >> vertices;
|
||||||
cout << endl;
|
std::cout << "Enter the Edges : ";
|
||||||
|
std::cin >> edges;
|
||||||
|
|
||||||
|
/// creating graph
|
||||||
|
std::vector<std::vector<size_t>> adj(vertices, std::vector<size_t>());
|
||||||
|
|
||||||
|
/// taking input for edges
|
||||||
|
std::cout << "Enter the vertices which have edges between them : "
|
||||||
|
<< std::endl;
|
||||||
|
while (edges--) {
|
||||||
|
size_t u, v;
|
||||||
|
std::cin >> u >> v;
|
||||||
|
graph::addEdge(&adj, u, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// running depth first search over graph
|
||||||
|
graph::depth_first_search(adj, 2);
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -1,52 +1,180 @@
|
|||||||
#include <cstdio>
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief [Graph Dijkstras Shortest Path Algorithm
|
||||||
|
* (Dijkstra's Shortest Path)]
|
||||||
|
* (https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)
|
||||||
|
*
|
||||||
|
* @author [Ayaan Khan](http://github.com/ayaankhan98)
|
||||||
|
*
|
||||||
|
* @details
|
||||||
|
* Dijkstra's Algorithm is used to find the shortest path from a source
|
||||||
|
* vertex to all other reachable vertex in the graph.
|
||||||
|
* The algorithm initially assumes all the nodes are unreachable from the
|
||||||
|
* given source vertex so we mark the distances of all vertices as INF
|
||||||
|
* (infinity) from source vertex (INF / infinity denotes unable to reach).
|
||||||
|
*
|
||||||
|
* in similar fashion with BFS we assume the distance of source vertex as 0
|
||||||
|
* and pushes the vertex in a priority queue with it's distance.
|
||||||
|
* we maintain the priority queue as a min heap so that we can get the
|
||||||
|
* minimum element at the top of heap
|
||||||
|
*
|
||||||
|
* Basically what we do in this algorithm is that we try to minimize the
|
||||||
|
* distances of all the reachable vertices from the current vertex, look
|
||||||
|
* at the code below to understand in better way.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
using namespace std;
|
#include <memory>
|
||||||
#define INF 10000010
|
|
||||||
vector<pair<int, int>> graph[5 * 100001];
|
|
||||||
int dis[5 * 100001];
|
|
||||||
int dij(vector<pair<int, int>> *v, int s, int *dis) {
|
|
||||||
priority_queue<pair<int, int>, vector<pair<int, int>>,
|
|
||||||
greater<pair<int, int>>>
|
|
||||||
pq;
|
|
||||||
// source distance to zero.
|
|
||||||
pq.push(make_pair(0, s));
|
|
||||||
dis[s] = 0;
|
|
||||||
int u;
|
|
||||||
while (!pq.empty()) {
|
|
||||||
u = (pq.top()).second;
|
|
||||||
pq.pop();
|
|
||||||
for (vector<pair<int, int>>::iterator it = v[u].begin();
|
|
||||||
it != v[u].end(); it++) {
|
|
||||||
if (dis[u] + it->first < dis[it->second]) {
|
|
||||||
dis[it->second] = dis[u] + it->first;
|
|
||||||
pq.push(make_pair(dis[it->second], it->second));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int main() {
|
|
||||||
int m, n, l, x, y, s;
|
|
||||||
// n--> number of nodes , m --> number of edges
|
|
||||||
cin >> n >> m;
|
|
||||||
for (int i = 0; i < m; i++) {
|
|
||||||
// input edges.
|
|
||||||
scanf("%d%d%d", &x, &y, &l);
|
|
||||||
graph[x].push_back(make_pair(l, y));
|
|
||||||
graph[y].push_back(
|
|
||||||
make_pair(l, x)); // comment this line for directed graph
|
|
||||||
}
|
|
||||||
// start node.
|
|
||||||
scanf("%d", &s);
|
|
||||||
// intialise all distances to infinity.
|
|
||||||
for (int i = 1; i <= n; i++) dis[i] = INF;
|
|
||||||
dij(graph, s, dis);
|
|
||||||
|
|
||||||
for (int i = 1; i <= n; i++)
|
constexpr int64_t INF = std::numeric_limits<int64_t>::max();
|
||||||
if (dis[i] == INF)
|
|
||||||
cout << "-1 ";
|
/**
|
||||||
else
|
* @namespace graph
|
||||||
cout << dis[i] << " ";
|
* @brief Graph Algorithms
|
||||||
return 0;
|
*/
|
||||||
|
|
||||||
|
namespace graph {
|
||||||
|
/**
|
||||||
|
* @brief Function that add edge between two nodes or vertices of graph
|
||||||
|
*
|
||||||
|
* @param u any node or vertex of graph
|
||||||
|
* @param v any node or vertex of graph
|
||||||
|
*/
|
||||||
|
void addEdge(std::vector<std::vector<std::pair<int, int>>> *adj, int u, int v,
|
||||||
|
int w) {
|
||||||
|
(*adj)[u - 1].push_back(std::make_pair(v - 1, w));
|
||||||
|
// (*adj)[v - 1].push_back(std::make_pair(u - 1, w));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function runs the dijkstra algorithm for some source vertex and
|
||||||
|
* target vertex in the graph and returns the shortest distance of target
|
||||||
|
* from the source.
|
||||||
|
*
|
||||||
|
* @param adj input graph
|
||||||
|
* @param s source vertex
|
||||||
|
* @param t target vertex
|
||||||
|
*
|
||||||
|
* @return shortest distance if target is reachable from source else -1 in
|
||||||
|
* case if target is not reachable from source.
|
||||||
|
*/
|
||||||
|
int dijkstra(std::vector<std::vector<std::pair<int, int>>> *adj, int s, int t) {
|
||||||
|
/// n denotes the number of vertices in graph
|
||||||
|
int n = adj->size();
|
||||||
|
|
||||||
|
/// setting all the distances initially to INF
|
||||||
|
std::vector<int64_t> dist(n, INF);
|
||||||
|
|
||||||
|
/// creating a min heap using priority queue
|
||||||
|
/// first element of pair contains the distance
|
||||||
|
/// second element of pair contains the vertex
|
||||||
|
std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>,
|
||||||
|
std::greater<std::pair<int, int>>>
|
||||||
|
pq;
|
||||||
|
|
||||||
|
/// pushing the source vertex 's' with 0 distance in min heap
|
||||||
|
pq.push(std::make_pair(0, s));
|
||||||
|
|
||||||
|
/// marking the distance of source as 0
|
||||||
|
dist[s] = 0;
|
||||||
|
|
||||||
|
while (!pq.empty()) {
|
||||||
|
/// second element of pair denotes the node / vertex
|
||||||
|
int currentNode = pq.top().second;
|
||||||
|
|
||||||
|
/// first element of pair denotes the distance
|
||||||
|
int currentDist = pq.top().first;
|
||||||
|
|
||||||
|
pq.pop();
|
||||||
|
|
||||||
|
/// for all the reachable vertex from the currently exploring vertex
|
||||||
|
/// we will try to minimize the distance
|
||||||
|
for (std::pair<int, int> edge : (*adj)[currentNode]) {
|
||||||
|
/// minimizing distances
|
||||||
|
if (currentDist + edge.second < dist[edge.first]) {
|
||||||
|
dist[edge.first] = currentDist + edge.second;
|
||||||
|
pq.push(std::make_pair(dist[edge.first], edge.first));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dist[t] != INF) {
|
||||||
|
return dist[t];
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} // namespace graph
|
||||||
|
|
||||||
|
/** Function to test the Algorithm */
|
||||||
|
void tests() {
|
||||||
|
std::cout << "Initiatinig Predefined Tests..." << std::endl;
|
||||||
|
std::cout << "Initiating Test 1..." << std::endl;
|
||||||
|
std::vector<std::vector<std::pair<int, int>>> adj1(
|
||||||
|
4, std::vector<std::pair<int, int>>());
|
||||||
|
graph::addEdge(&adj1, 1, 2, 1);
|
||||||
|
graph::addEdge(&adj1, 4, 1, 2);
|
||||||
|
graph::addEdge(&adj1, 2, 3, 2);
|
||||||
|
graph::addEdge(&adj1, 1, 3, 5);
|
||||||
|
|
||||||
|
int s = 1, t = 3;
|
||||||
|
assert(graph::dijkstra(&adj1, s - 1, t - 1) == 3);
|
||||||
|
std::cout << "Test 1 Passed..." << std::endl;
|
||||||
|
|
||||||
|
s = 4, t = 3;
|
||||||
|
std::cout << "Initiating Test 2..." << std::endl;
|
||||||
|
assert(graph::dijkstra(&adj1, s - 1, t - 1) == 5);
|
||||||
|
std::cout << "Test 2 Passed..." << std::endl;
|
||||||
|
|
||||||
|
std::vector<std::vector<std::pair<int, int>>> adj2(
|
||||||
|
5, std::vector<std::pair<int, int>>());
|
||||||
|
graph::addEdge(&adj2, 1, 2, 4);
|
||||||
|
graph::addEdge(&adj2, 1, 3, 2);
|
||||||
|
graph::addEdge(&adj2, 2, 3, 2);
|
||||||
|
graph::addEdge(&adj2, 3, 2, 1);
|
||||||
|
graph::addEdge(&adj2, 2, 4, 2);
|
||||||
|
graph::addEdge(&adj2, 3, 5, 4);
|
||||||
|
graph::addEdge(&adj2, 5, 4, 1);
|
||||||
|
graph::addEdge(&adj2, 2, 5, 3);
|
||||||
|
graph::addEdge(&adj2, 3, 4, 4);
|
||||||
|
|
||||||
|
s = 1, t = 5;
|
||||||
|
std::cout << "Initiating Test 3..." << std::endl;
|
||||||
|
assert(graph::dijkstra(&adj2, s - 1, t - 1) == 6);
|
||||||
|
std::cout << "Test 3 Passed..." << std::endl;
|
||||||
|
std::cout << "All Test Passed..." << std::endl << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Main function */
|
||||||
|
int main() {
|
||||||
|
// running predefined tests
|
||||||
|
tests();
|
||||||
|
|
||||||
|
int vertices = int(), edges = int();
|
||||||
|
std::cout << "Enter the number of vertices : ";
|
||||||
|
std::cin >> vertices;
|
||||||
|
std::cout << "Enter the number of edges : ";
|
||||||
|
std::cin >> edges;
|
||||||
|
|
||||||
|
std::vector<std::vector<std::pair<int, int>>> adj(
|
||||||
|
vertices, std::vector<std::pair<int, int>>());
|
||||||
|
|
||||||
|
int u = int(), v = int(), w = int();
|
||||||
|
while (edges--) {
|
||||||
|
std::cin >> u >> v >> w;
|
||||||
|
graph::addEdge(&adj, u, v, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
int s = int(), t = int();
|
||||||
|
std::cin >> s >> t;
|
||||||
|
int dist = graph::dijkstra(&adj, s - 1, t - 1);
|
||||||
|
if (dist == -1) {
|
||||||
|
std::cout << "Target not reachable from source" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Shortest Path Distance : " << dist << std::endl;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterative function/method to print graph:
|
* Iterative function/method to print graph:
|
||||||
@ -13,13 +13,13 @@ using namespace std;
|
|||||||
* @param V : vertices
|
* @param V : vertices
|
||||||
* @return void
|
* @return void
|
||||||
**/
|
**/
|
||||||
void print(vector<int> a[], int V) {
|
void print(std::vector<int> a[], int V) {
|
||||||
for (int i = 0; i < V; i++) {
|
for (int i = 0; i < V; i++) {
|
||||||
if (!a[i].empty())
|
if (!a[i].empty())
|
||||||
cout << "i=" << i << "-->";
|
std::cout << "i=" << i << "-->";
|
||||||
for (int j = 0; j < a[i].size(); j++) cout << a[i][j] << " ";
|
for (int j = 0; j < a[i].size(); j++) std::cout << a[i][j] << " ";
|
||||||
if (!a[i].empty())
|
if (!a[i].empty())
|
||||||
cout << endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ void print(vector<int> a[], int V) {
|
|||||||
* @param adj[] : array of vectors to represent graph
|
* @param adj[] : array of vectors to represent graph
|
||||||
* @return void
|
* @return void
|
||||||
**/
|
**/
|
||||||
void push_vertex(int v, stack<int> &st, bool vis[], vector<int> adj[]) {
|
void push_vertex(int v, std::stack<int> &st, bool vis[], std::vector<int> adj[]) {
|
||||||
vis[v] = true;
|
vis[v] = true;
|
||||||
for (auto i = adj[v].begin(); i != adj[v].end(); i++) {
|
for (auto i = adj[v].begin(); i != adj[v].end(); i++) {
|
||||||
if (vis[*i] == false)
|
if (vis[*i] == false)
|
||||||
@ -47,7 +47,7 @@ void push_vertex(int v, stack<int> &st, bool vis[], vector<int> adj[]) {
|
|||||||
* @param grev[] : graph with reversed edges
|
* @param grev[] : graph with reversed edges
|
||||||
* @return void
|
* @return void
|
||||||
**/
|
**/
|
||||||
void dfs(int v, bool vis[], vector<int> grev[]) {
|
void dfs(int v, bool vis[], std::vector<int> grev[]) {
|
||||||
vis[v] = true;
|
vis[v] = true;
|
||||||
// cout<<v<<" ";
|
// cout<<v<<" ";
|
||||||
for (auto i = grev[v].begin(); i != grev[v].end(); i++) {
|
for (auto i = grev[v].begin(); i != grev[v].end(); i++) {
|
||||||
@ -66,15 +66,15 @@ no SCCs i.e. none(0) or there will be x no. of SCCs (x>0)) i.e. it returns the
|
|||||||
count of (number of) strongly connected components (SCCs) in the graph.
|
count of (number of) strongly connected components (SCCs) in the graph.
|
||||||
(variable 'count_scc' within function)
|
(variable 'count_scc' within function)
|
||||||
**/
|
**/
|
||||||
int kosaraju(int V, vector<int> adj[]) {
|
int kosaraju(int V, std::vector<int> adj[]) {
|
||||||
bool vis[V] = {};
|
bool vis[V] = {};
|
||||||
stack<int> st;
|
std::stack<int> st;
|
||||||
for (int v = 0; v < V; v++) {
|
for (int v = 0; v < V; v++) {
|
||||||
if (vis[v] == false)
|
if (vis[v] == false)
|
||||||
push_vertex(v, st, vis, adj);
|
push_vertex(v, st, vis, adj);
|
||||||
}
|
}
|
||||||
// making new graph (grev) with reverse edges as in adj[]:
|
// making new graph (grev) with reverse edges as in adj[]:
|
||||||
vector<int> grev[V];
|
std::vector<int> grev[V];
|
||||||
for (int i = 0; i < V + 1; i++) {
|
for (int i = 0; i < V + 1; i++) {
|
||||||
for (auto j = adj[i].begin(); j != adj[i].end(); j++) {
|
for (auto j = adj[i].begin(); j != adj[i].end(); j++) {
|
||||||
grev[*j].push_back(i);
|
grev[*j].push_back(i);
|
||||||
@ -102,20 +102,20 @@ int kosaraju(int V, vector<int> adj[]) {
|
|||||||
// Input your required values: (not hardcoded)
|
// Input your required values: (not hardcoded)
|
||||||
int main() {
|
int main() {
|
||||||
int t;
|
int t;
|
||||||
cin >> t;
|
std::cin >> t;
|
||||||
while (t--) {
|
while (t--) {
|
||||||
int a, b; // a->number of nodes, b->directed edges.
|
int a, b; // a->number of nodes, b->directed edges.
|
||||||
cin >> a >> b;
|
std::cin >> a >> b;
|
||||||
int m, n;
|
int m, n;
|
||||||
vector<int> adj[a + 1];
|
std::vector<int> adj[a + 1];
|
||||||
for (int i = 0; i < b; i++) // take total b inputs of 2 vertices each
|
for (int i = 0; i < b; i++) // take total b inputs of 2 vertices each
|
||||||
// required to form an edge.
|
// required to form an edge.
|
||||||
{
|
{
|
||||||
cin >> m >> n; // take input m,n denoting edge from m->n.
|
std::cin >> m >> n; // take input m,n denoting edge from m->n.
|
||||||
adj[m].push_back(n);
|
adj[m].push_back(n);
|
||||||
}
|
}
|
||||||
// pass number of nodes and adjacency array as parameters to function:
|
// pass number of nodes and adjacency array as parameters to function:
|
||||||
cout << kosaraju(a, adj) << endl;
|
std::cout << kosaraju(a, adj) << std::endl;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
//#include <boost/multiprecision/cpp_int.hpp>
|
//#include <boost/multiprecision/cpp_int.hpp>
|
||||||
// using namespace boost::multiprecision;
|
// using namespace boost::multiprecision;
|
||||||
const int mx = 1e6 + 5;
|
const int mx = 1e6 + 5;
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
//#include<bits/stdc++.h>
|
//#include<bits/stdc++.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
using namespace std;
|
#include <cmath>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
// Find the lowest common ancestor using binary lifting in O(nlogn)
|
// Find the lowest common ancestor using binary lifting in O(nlogn)
|
||||||
// Zero based indexing
|
// Zero based indexing
|
||||||
// Resource : https://cp-algorithms.com/graph/lca_binary_lifting.html
|
// Resource : https://cp-algorithms.com/graph/lca_binary_lifting.html
|
||||||
@ -9,7 +11,7 @@ const int N = 1005;
|
|||||||
const int LG = log2(N) + 1;
|
const int LG = log2(N) + 1;
|
||||||
struct lca {
|
struct lca {
|
||||||
int n;
|
int n;
|
||||||
vector<int> adj[N]; // Graph
|
std::vector<int> adj[N]; // Graph
|
||||||
int up[LG][N]; // build this table
|
int up[LG][N]; // build this table
|
||||||
int level[N]; // get the levels of all of them
|
int level[N]; // get the levels of all of them
|
||||||
|
|
||||||
@ -18,7 +20,7 @@ struct lca {
|
|||||||
memset(level, 0, sizeof(level));
|
memset(level, 0, sizeof(level));
|
||||||
for (int i = 0; i < n - 1; ++i) {
|
for (int i = 0; i < n - 1; ++i) {
|
||||||
int a, b;
|
int a, b;
|
||||||
cin >> a >> b;
|
std::cin >> a >> b;
|
||||||
a--;
|
a--;
|
||||||
b--;
|
b--;
|
||||||
adj[a].push_back(b);
|
adj[a].push_back(b);
|
||||||
@ -30,15 +32,15 @@ struct lca {
|
|||||||
}
|
}
|
||||||
void verify() {
|
void verify() {
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
cout << i << " : level: " << level[i] << endl;
|
std::cout << i << " : level: " << level[i] << std::endl;
|
||||||
}
|
}
|
||||||
cout << endl;
|
std::cout << std::endl;
|
||||||
for (int i = 0; i < LG; ++i) {
|
for (int i = 0; i < LG; ++i) {
|
||||||
cout << "Power:" << i << ": ";
|
std::cout << "Power:" << i << ": ";
|
||||||
for (int j = 0; j < n; ++j) {
|
for (int j = 0; j < n; ++j) {
|
||||||
cout << up[i][j] << " ";
|
std::cout << up[i][j] << " ";
|
||||||
}
|
}
|
||||||
cout << endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +67,7 @@ struct lca {
|
|||||||
u--;
|
u--;
|
||||||
v--;
|
v--;
|
||||||
if (level[v] > level[u]) {
|
if (level[v] > level[u]) {
|
||||||
swap(u, v);
|
std::swap(u, v);
|
||||||
}
|
}
|
||||||
// u is at the bottom.
|
// u is at the bottom.
|
||||||
int dist = level[u] - level[v];
|
int dist = level[u] - level[v];
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
int n, m; // For number of Vertices (V) and number of edges (E)
|
int n, m; // For number of Vertices (V) and number of edges (E)
|
||||||
vector<vector<int>> G;
|
std::vector<std::vector<int>> G;
|
||||||
vector<bool> visited;
|
std::vector<bool> visited;
|
||||||
vector<int> ans;
|
std::vector<int> ans;
|
||||||
|
|
||||||
void dfs(int v) {
|
void dfs(int v) {
|
||||||
visited[v] = true;
|
visited[v] = true;
|
||||||
@ -27,21 +26,21 @@ void topological_sort() {
|
|||||||
reverse(ans.begin(), ans.end());
|
reverse(ans.begin(), ans.end());
|
||||||
}
|
}
|
||||||
int main() {
|
int main() {
|
||||||
cout << "Enter the number of vertices and the number of directed edges\n";
|
std::cout << "Enter the number of vertices and the number of directed edges\n";
|
||||||
cin >> n >> m;
|
std::cin >> n >> m;
|
||||||
int x, y;
|
int x, y;
|
||||||
G.resize(n, vector<int>());
|
G.resize(n, std::vector<int>());
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
cin >> x >> y;
|
std::cin >> x >> y;
|
||||||
x--, y--; // to convert 1-indexed to 0-indexed
|
x--, y--; // to convert 1-indexed to 0-indexed
|
||||||
G[x].push_back(y);
|
G[x].push_back(y);
|
||||||
}
|
}
|
||||||
topological_sort();
|
topological_sort();
|
||||||
cout << "Topological Order : \n";
|
std::cout << "Topological Order : \n";
|
||||||
for (int v : ans) {
|
for (int v : ans) {
|
||||||
cout << v + 1
|
std::cout << v + 1
|
||||||
<< ' '; // converting zero based indexing back to one based.
|
<< ' '; // converting zero based indexing back to one based.
|
||||||
}
|
}
|
||||||
cout << '\n';
|
std::cout << '\n';
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user