mirror of
https://github.com/TheAlgorithms/C-Plus-Plus.git
synced 2026-06-30 17:16:30 +08:00
Merge branch 'master' into is_graph_bipartite
This commit is contained in:
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} )
|
||||
@@ -53,7 +53,7 @@ using AdjList = std::map<unsigned int, std::vector<unsigned int>>;
|
||||
*/
|
||||
class Graph {
|
||||
public:
|
||||
Graph() : m_vertices(0), m_adjList({}) {}
|
||||
Graph() : m_adjList({}) {}
|
||||
~Graph() = default;
|
||||
Graph(Graph&&) = default;
|
||||
Graph& operator=(Graph&&) = default;
|
||||
@@ -65,8 +65,8 @@ class Graph {
|
||||
* @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 const& adjList)
|
||||
: m_vertices(vertices), m_adjList(adjList) {}
|
||||
Graph(unsigned int vertices, AdjList adjList)
|
||||
: m_vertices(vertices), m_adjList(std::move(adjList)) {}
|
||||
|
||||
/** Create a graph from vertices and adjacency list.
|
||||
*
|
||||
@@ -142,7 +142,7 @@ class Graph {
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int m_vertices;
|
||||
unsigned int m_vertices = 0;
|
||||
AdjList m_adjList;
|
||||
};
|
||||
|
||||
|
||||
133
graph/depth_first_search.cpp
Normal file
133
graph/depth_first_search.cpp
Normal file
@@ -0,0 +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 <vector>
|
||||
|
||||
/**
|
||||
*
|
||||
* \namespace graph
|
||||
* \brief Graph Algorithms
|
||||
*
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief
|
||||
* initiates depth first search algorithm.
|
||||
*
|
||||
* @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() {
|
||||
size_t vertices = 0, edges = 0;
|
||||
std::cout << "Enter the Vertices : ";
|
||||
std::cin >> vertices;
|
||||
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 = 0, v = 0;
|
||||
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;
|
||||
}
|
||||
46
graph/depth_first_search_with_stack.cpp
Normal file
46
graph/depth_first_search_with_stack.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
|
||||
constexpr int WHITE = 0;
|
||||
constexpr int GREY = 1;
|
||||
constexpr int BLACK = 2;
|
||||
constexpr int INF = 99999;
|
||||
|
||||
void dfs(const std::vector< std::list<int> > &graph, int start) {
|
||||
std::vector<int> checked(graph.size(), WHITE);
|
||||
checked[start] = GREY;
|
||||
std::stack<int> stack;
|
||||
stack.push(start);
|
||||
while (!stack.empty()) {
|
||||
int act = stack.top();
|
||||
stack.pop();
|
||||
|
||||
if (checked[act] == GREY) {
|
||||
std::cout << act << ' ';
|
||||
for (auto it : graph[act]) {
|
||||
stack.push(it);
|
||||
if (checked[it] != BLACK) {
|
||||
checked[it] = GREY;
|
||||
}
|
||||
}
|
||||
checked[act] = BLACK; // nodo controllato
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
int n = 0;
|
||||
std::cin >> n;
|
||||
std::vector< std::list<int> > graph(INF);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
int u = 0, w = 0;
|
||||
std::cin >> u >> w;
|
||||
graph[u].push_back(w);
|
||||
}
|
||||
|
||||
dfs(graph, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
int v = 4;
|
||||
void DFSUtil_(int graph[4][4], bool visited[], int s) {
|
||||
visited[s] = true;
|
||||
cout << s << " ";
|
||||
for (int i = 0; i < v; i++) {
|
||||
if (graph[s][i] == 1 && visited[i] == false) {
|
||||
DFSUtil_(graph, visited, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DFS_(int graph[4][4], int s) {
|
||||
bool visited[v];
|
||||
memset(visited, 0, sizeof(visited));
|
||||
DFSUtil_(graph, visited, s);
|
||||
}
|
||||
|
||||
int main() {
|
||||
int graph[4][4] = {{0, 1, 1, 0}, {0, 0, 1, 0}, {1, 0, 0, 1}, {0, 0, 0, 1}};
|
||||
cout << "DFS: ";
|
||||
DFS_(graph, 2);
|
||||
cout << endl;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
|
||||
#define WHITE 0
|
||||
#define GREY 1
|
||||
#define BLACK 2
|
||||
#define INF 99999
|
||||
|
||||
using namespace std;
|
||||
|
||||
int checked[999] = {WHITE};
|
||||
|
||||
void dfs(const list<int> lista[], int start) {
|
||||
stack<int> stack;
|
||||
|
||||
int checked[999] = {WHITE};
|
||||
|
||||
stack.push(start);
|
||||
|
||||
checked[start] = GREY;
|
||||
while (!stack.empty()) {
|
||||
int act = stack.top();
|
||||
stack.pop();
|
||||
|
||||
if (checked[act] == GREY) {
|
||||
cout << act << ' ';
|
||||
for (auto it = lista[act].begin(); it != lista[act].end(); ++it) {
|
||||
stack.push(*it);
|
||||
if (checked[*it] != BLACK)
|
||||
checked[*it] = GREY;
|
||||
}
|
||||
checked[act] = BLACK; // nodo controllato
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
int u, w;
|
||||
int n;
|
||||
cin >> n;
|
||||
list<int> lista[INF];
|
||||
for (int i = 0; i < n; ++i) {
|
||||
cin >> u >> w;
|
||||
lista[u].push_back(w);
|
||||
}
|
||||
|
||||
dfs(lista, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4,77 +4,84 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* Iterative function/method to print graph:
|
||||
* @param a[] : array of vectors (2D)
|
||||
* @param V : vertices
|
||||
* @param a adjacency list representation of the graph
|
||||
* @param V number of vertices
|
||||
* @return void
|
||||
**/
|
||||
void print(vector<int> a[], int V) {
|
||||
void print(const std::vector< std::vector<int> > &a, int V) {
|
||||
for (int i = 0; i < V; i++) {
|
||||
if (!a[i].empty())
|
||||
cout << "i=" << i << "-->";
|
||||
for (int j = 0; j < a[i].size(); j++) cout << a[i][j] << " ";
|
||||
if (!a[i].empty())
|
||||
cout << endl;
|
||||
if (!a[i].empty()) {
|
||||
std::cout << "i=" << i << "-->";
|
||||
}
|
||||
for (int j : a[i]) {
|
||||
std::cout << j << " ";
|
||||
}
|
||||
if (!a[i].empty()) {
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* //Recursive function/method to push vertices into stack passed as parameter:
|
||||
* @param v : vertices
|
||||
* @param &st : stack passed by reference
|
||||
* @param vis[] : array to keep track of visited nodes (boolean type)
|
||||
* @param adj[] : array of vectors to represent graph
|
||||
* @param v vertices
|
||||
* @param st stack passed by reference
|
||||
* @param vis array to keep track of visited nodes (boolean type)
|
||||
* @param adj adjacency list representation of the graph
|
||||
* @return void
|
||||
**/
|
||||
void push_vertex(int v, stack<int> &st, bool vis[], vector<int> adj[]) {
|
||||
vis[v] = true;
|
||||
void push_vertex(int v, std::stack<int> *st, std::vector<bool> *vis, const std::vector< std::vector<int> > &adj) {
|
||||
(*vis)[v] = true;
|
||||
for (auto i = adj[v].begin(); i != adj[v].end(); i++) {
|
||||
if (vis[*i] == false)
|
||||
if ((*vis)[*i] == false) {
|
||||
push_vertex(*i, st, vis, adj);
|
||||
}
|
||||
}
|
||||
st.push(v);
|
||||
st->push(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* //Recursive function/method to implement depth first traversal(dfs):
|
||||
* @param v : vertices
|
||||
* @param vis[] : array to keep track of visited nodes (boolean type)
|
||||
* @param grev[] : graph with reversed edges
|
||||
* @param v vertices
|
||||
* @param vis array to keep track of visited nodes (boolean type)
|
||||
* @param grev graph with reversed edges
|
||||
* @return void
|
||||
**/
|
||||
void dfs(int v, bool vis[], vector<int> grev[]) {
|
||||
vis[v] = true;
|
||||
void dfs(int v, std::vector<bool> *vis, const std::vector< std::vector<int> > &grev) {
|
||||
(*vis)[v] = true;
|
||||
// cout<<v<<" ";
|
||||
for (auto i = grev[v].begin(); i != grev[v].end(); i++) {
|
||||
if (vis[*i] == false)
|
||||
if ((*vis)[*i] == false) {
|
||||
dfs(*i, vis, grev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// function/method to implement Kosaraju's Algorithm:
|
||||
/**
|
||||
* Info about the method
|
||||
* @param V : vertices in graph
|
||||
* @param adj[] : array of vectors that represent a graph (adjacency list/array)
|
||||
* @param V vertices in graph
|
||||
* @param adj array of vectors that represent a graph (adjacency list/array)
|
||||
* @return int ( 0, 1, 2..and so on, only unsigned values as either there can be
|
||||
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.
|
||||
(variable 'count_scc' within function)
|
||||
**/
|
||||
int kosaraju(int V, vector<int> adj[]) {
|
||||
bool vis[V] = {};
|
||||
stack<int> st;
|
||||
int kosaraju(int V, const std::vector< std::vector<int> > &adj) {
|
||||
std::vector<bool> vis(V, false);
|
||||
std::stack<int> st;
|
||||
for (int v = 0; v < V; v++) {
|
||||
if (vis[v] == false)
|
||||
push_vertex(v, st, vis, adj);
|
||||
if (vis[v] == false) {
|
||||
push_vertex(v, &st, &vis, adj);
|
||||
}
|
||||
}
|
||||
// making new graph (grev) with reverse edges as in adj[]:
|
||||
vector<int> grev[V];
|
||||
std::vector< std::vector<int> > grev(V);
|
||||
for (int i = 0; i < V + 1; i++) {
|
||||
for (auto j = adj[i].begin(); j != adj[i].end(); j++) {
|
||||
grev[*j].push_back(i);
|
||||
@@ -89,7 +96,7 @@ int kosaraju(int V, vector<int> adj[]) {
|
||||
int t = st.top();
|
||||
st.pop();
|
||||
if (vis[t] == false) {
|
||||
dfs(t, vis, grev);
|
||||
dfs(t, &vis, grev);
|
||||
count_scc++;
|
||||
}
|
||||
}
|
||||
@@ -101,21 +108,21 @@ int kosaraju(int V, vector<int> adj[]) {
|
||||
// All critical/corner cases have been taken care of.
|
||||
// Input your required values: (not hardcoded)
|
||||
int main() {
|
||||
int t;
|
||||
cin >> t;
|
||||
int t = 0;
|
||||
std::cin >> t;
|
||||
while (t--) {
|
||||
int a, b; // a->number of nodes, b->directed edges.
|
||||
cin >> a >> b;
|
||||
int m, n;
|
||||
vector<int> adj[a + 1];
|
||||
int a = 0, b = 0; // a->number of nodes, b->directed edges.
|
||||
std::cin >> a >> b;
|
||||
int m = 0, n = 0;
|
||||
std::vector< std::vector<int> > adj(a + 1);
|
||||
for (int i = 0; i < b; i++) // take total b inputs of 2 vertices each
|
||||
// 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);
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -1,73 +1,21 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
//#include <boost/multiprecision/cpp_int.hpp>
|
||||
// using namespace boost::multiprecision;
|
||||
const int mx = 1e6 + 5;
|
||||
const long int inf = 2e9;
|
||||
typedef long long ll;
|
||||
#define rep(i, n) for (i = 0; i < n; i++)
|
||||
#define repp(i, a, b) for (i = a; i <= b; i++)
|
||||
#define pii pair<int, int>
|
||||
#define vpii vector<pii>
|
||||
#define vi vector<int>
|
||||
#define vll vector<ll>
|
||||
#define r(x) scanf("%d", &x)
|
||||
#define rs(s) scanf("%s", s)
|
||||
#define gc getchar_unlocked
|
||||
#define pc putchar_unlocked
|
||||
#define mp make_pair
|
||||
#define pb push_back
|
||||
#define lb lower_bound
|
||||
#define ub upper_bound
|
||||
#define endl "\n"
|
||||
#define fast \
|
||||
ios_base::sync_with_stdio(false); \
|
||||
cin.tie(NULL); \
|
||||
cout.tie(NULL);
|
||||
using namespace std;
|
||||
void in(int &x) {
|
||||
register int c = gc();
|
||||
x = 0;
|
||||
int neg = 0;
|
||||
for (; ((c < 48 || c > 57) && c != '-'); c = gc())
|
||||
;
|
||||
if (c == '-') {
|
||||
neg = 1;
|
||||
c = gc();
|
||||
}
|
||||
for (; c > 47 && c < 58; c = gc()) {
|
||||
x = (x << 1) + (x << 3) + c - 48;
|
||||
}
|
||||
if (neg)
|
||||
x = -x;
|
||||
}
|
||||
void out(int n) {
|
||||
int N = n, rev, count = 0;
|
||||
rev = N;
|
||||
if (N == 0) {
|
||||
pc('0');
|
||||
return;
|
||||
}
|
||||
while ((rev % 10) == 0) {
|
||||
count++;
|
||||
rev /= 10;
|
||||
}
|
||||
rev = 0;
|
||||
while (N != 0) {
|
||||
rev = (rev << 3) + (rev << 1) + N % 10;
|
||||
N /= 10;
|
||||
}
|
||||
while (rev != 0) {
|
||||
pc(rev % 10 + '0');
|
||||
rev /= 10;
|
||||
}
|
||||
while (count--) pc('0');
|
||||
}
|
||||
ll parent[mx], arr[mx], node, edge;
|
||||
vector<pair<ll, pair<ll, ll>>> v;
|
||||
using ll = int64_t;
|
||||
|
||||
std::array<ll, mx> parent;
|
||||
ll node, edge;
|
||||
std::vector<std::pair<ll, std::pair<ll, ll>>> edges;
|
||||
void initial() {
|
||||
int i;
|
||||
rep(i, node + edge) parent[i] = i;
|
||||
for (int i = 0; i < node + edge; ++i) {
|
||||
parent[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
int root(int i) {
|
||||
while (parent[i] != i) {
|
||||
parent[i] = parent[parent[i]];
|
||||
@@ -75,41 +23,42 @@ int root(int i) {
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void join(int x, int y) {
|
||||
int root_x = root(x); // Disjoint set union by rank
|
||||
int root_y = root(y);
|
||||
parent[root_x] = root_y;
|
||||
}
|
||||
|
||||
ll kruskal() {
|
||||
ll mincost = 0, i, x, y;
|
||||
rep(i, edge) {
|
||||
x = v[i].second.first;
|
||||
y = v[i].second.second;
|
||||
ll mincost = 0;
|
||||
for (int i = 0; i < edge; ++i) {
|
||||
ll x = edges[i].second.first;
|
||||
ll y = edges[i].second.second;
|
||||
if (root(x) != root(y)) {
|
||||
mincost += v[i].first;
|
||||
mincost += edges[i].first;
|
||||
join(x, y);
|
||||
}
|
||||
}
|
||||
return mincost;
|
||||
}
|
||||
|
||||
int main() {
|
||||
fast;
|
||||
while (1) {
|
||||
int i, j, from, to, cost, totalcost = 0;
|
||||
cin >> node >> edge; // Enter the nodes and edges
|
||||
if (node == 0 && edge == 0)
|
||||
while (true) {
|
||||
int from = 0, to = 0, cost = 0, totalcost = 0;
|
||||
std::cin >> node >> edge; // Enter the nodes and edges
|
||||
if (node == 0 && edge == 0) {
|
||||
break; // Enter 0 0 to break out
|
||||
}
|
||||
initial(); // Initialise the parent array
|
||||
rep(i, edge) {
|
||||
cin >> from >> to >> cost;
|
||||
v.pb(mp(cost, mp(from, to)));
|
||||
for (int i = 0; i < edge; ++i) {
|
||||
std::cin >> from >> to >> cost;
|
||||
edges.emplace_back(make_pair(cost, std::make_pair(from, to)));
|
||||
totalcost += cost;
|
||||
}
|
||||
sort(v.begin(), v.end());
|
||||
// rep(i,v.size())
|
||||
// cout<<v[i].first<<" ";
|
||||
cout << kruskal() << endl;
|
||||
v.clear();
|
||||
sort(edges.begin(), edges.end());
|
||||
std::cout << kruskal() << std::endl;
|
||||
edges.clear();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user