diff --git a/CPP/algorithms/graph_algorithms/dijkstra_algorithm.cpp b/CPP/algorithms/graph_algorithms/dijkstra_algorithm.cpp new file mode 100644 index 00000000..081c184b --- /dev/null +++ b/CPP/algorithms/graph_algorithms/dijkstra_algorithm.cpp @@ -0,0 +1,154 @@ +// Dijkstra’s Algorithm — Single Source Shortest Path +// Problem +// Given a weighted graph with non-negative edge weights, +// find the shortest path from a source vertex to all other vertices. +// +// Approach +// 1. Use a priority queue (min-heap) to always expand the next closest vertex. +// 2. Initialize distances[] with infinity, except source = 0. +// 3. While queue not empty: +// - Extract vertex u with smallest dist[u]. +// - For each neighbor v of u, relax edge (u,v): +// if dist[u] + weight(u,v) < dist[v], update dist[v]. +// +// Complexity +// Time : O((V + E) log V) — using priority queue +// Space : O(V + E) — adjacency list + distance array + heap +// +// Input +// - Number of vertices (V) +// - Number of edges (E) +// - Edge list {u, v, w} (u → v with weight w) +// - Source vertex (src) +// +// Output +// - Shortest distance from src to all vertices + +#include +#include +#include +#include +using namespace std; + +int main() +{ + ios::sync_with_stdio(false); + cin.tie(nullptr); + + int V, E; + cin >> V >> E; + vector>> adj(V); + + for (int i = 0; i < E; i++) + { + int u, v, w; + cin >> u >> v >> w; + adj[u].push_back({v, w}); + adj[v].push_back({u, w}); // undirected; remove if directed + } + + int src; + cin >> src; + + const int INF = numeric_limits::max(); + vector dist(V, INF); + dist[src] = 0; + + // min-heap {distance, vertex} + priority_queue, vector>, greater<>> pq; + pq.push({0, src}); + + while (!pq.empty()) + { + int d = pq.top().first; + int u = pq.top().second; + pq.pop(); + if (d > dist[u]) + continue; // outdated entry + + for (auto &edge : adj[u]) + { + int v = edge.first, w = edge.second; + if (dist[u] + w < dist[v]) + { + dist[v] = dist[u] + w; + pq.push({dist[v], v}); + } + } + } + + cout << "Shortest distances from source " << src << ":\n"; + for (int i = 0; i < V; i++) + { + if (dist[i] == INF) + cout << i << " : INF\n"; + else + cout << i << " : " << dist[i] << "\n"; + } + + return 0; +} + +/* +Example Input: +5 6 +0 1 2 +0 2 4 +1 2 1 +1 3 7 +2 4 3 +3 4 1 +0 + +Visualization: +Graph: + (2) + 0 ------- 1 + \ / \ + (4)\ (1) (7) + \ / \ + 2 ------- 3 + \ / + (3) (1) + \ / + 4 + +Execution: +dist = [0, INF, INF, INF, INF] +Start from src=0 + +Step 1: Pick 0 → dist[0]=0 + Relax edges: + 0→1 (2) → dist[1]=2 + 0→2 (4) → dist[2]=4 +dist = [0,2,4,INF,INF] + +Step 2: Pick 1 (dist=2) + Relax edges: + 1→2 (1) → dist[2]=min(4,2+1)=3 + 1→3 (7) → dist[3]=2+7=9 +dist = [0,2,3,9,INF] + +Step 3: Pick 2 (dist=3) + Relax edges: + 2→4 (3) → dist[4]=3+3=6 +dist = [0,2,3,9,6] + +Step 4: Pick 4 (dist=6) → relax 4→3 (1): + dist[3]=min(9,6+1)=7 +dist = [0,2,3,7,6] + +Step 5: Pick 3 (dist=7) → no better updates + +Final distances from 0: +0 : 0 +1 : 2 +2 : 3 +3 : 7 +4 : 6 + +Time : O((V+E) log V) +Space : O(V+E) +*/ + +// add: Dijkstra PR diff --git a/CPP/algorithms/graph_algorithms/floyd_warshall.cpp b/CPP/algorithms/graph_algorithms/floyd_warshall.cpp new file mode 100644 index 00000000..b7433c28 --- /dev/null +++ b/CPP/algorithms/graph_algorithms/floyd_warshall.cpp @@ -0,0 +1,134 @@ +// Floyd–Warshall Algorithm — All-Pairs Shortest Path +// Problem +// Compute shortest distances between every pair of vertices in a weighted graph. +// +// Approach +// 1. Initialize dist[i][j]: +// - 0 if i==j +// - weight(u,v) if edge exists +// - INF otherwise +// 2. For k in [0..V-1] (intermediate vertex): +// for i in [0..V-1] (source): +// for j in [0..V-1] (destination): +// dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]) +// 3. After all iterations, dist[i][j] is the shortest distance. +// +// Complexity +// Time : O(V^3) +// Space : O(V^2) + +#include +#include +#include +using namespace std; + +int main() +{ + ios::sync_with_stdio(false); + cin.tie(nullptr); + + int V, E; + cin >> V >> E; + const int INF = 1e9; + + vector> dist(V, vector(V, INF)); + for (int i = 0; i < V; i++) + dist[i][i] = 0; + + for (int i = 0; i < E; i++) + { + int u, v, w; + cin >> u >> v >> w; + dist[u][v] = min(dist[u][v], w); + dist[v][u] = min(dist[v][u], w); // remove if directed + } + + cout << "Initial distance matrix:\n"; + for (auto &row : dist) + { + for (auto x : row) + cout << (x == INF ? -1 : x) << " "; + cout << "\n"; + } + cout << "\n"; + + // Floyd–Warshall dry run + for (int k = 0; k < V; k++) + { + cout << "Considering intermediate vertex k=" << k << ":\n"; + for (int i = 0; i < V; i++) + for (int j = 0; j < V; j++) + if (dist[i][k] < INF && dist[k][j] < INF) + dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]); + + // print matrix after this k + for (auto &row : dist) + { + for (auto x : row) + cout << (x == INF ? -1 : x) << " "; + cout << "\n"; + } + cout << "\n"; + } + + cout << "Final All-Pairs Shortest Distances:\n"; + for (auto &row : dist) + { + for (auto x : row) + cout << (x == INF ? -1 : x) << " "; + cout << "\n"; + } + + return 0; +} + +/* +Example Input: +4 5 +0 1 5 +0 3 10 +1 2 3 +2 3 1 +0 2 100 + +Visualization: +Graph: + (5) (3) (1) +0 ----- 1 -------- 2 -------- 3 + \ ^ + \____________ (10) ___________/ + +Dry Run Steps: + +Initial dist: +0 5 100 10 +5 0 3 -1 +100 3 0 1 +10 -1 1 0 + +k = 0 (using vertex 0 as intermediate): +- dist[2][3] = min(1, dist[2][0]+dist[0][3]) = min(1,100+10)=1 (no change) +- dist[2][0] = min(100, dist[2][0]+dist[0][0]) = 100 (no change) +... print matrix + +k = 1 (vertex 1 intermediate): +- dist[0][2] = min(100, dist[0][1]+dist[1][2]) = min(100,5+3)=8 +- dist[3][0] = min(10, dist[3][1]+dist[1][0]) = min(10, INF+5)=10 (no change) +... print matrix + +k = 2 (vertex 2 intermediate): +- dist[0][3] = min(10, dist[0][2]+dist[2][3]) = min(10,8+1)=9 +- dist[1][3] = min(INF, 3+1)=4 +... print matrix + +k = 3 (vertex 3 intermediate): +- no further updates + +Final dist: +0 5 8 9 +5 0 3 4 +8 3 0 1 +9 4 1 0 +*/ + +// prepare PR diff --git a/CPP/algorithms/graph_algorithms/kosaraju_algorithm.cpp b/CPP/algorithms/graph_algorithms/kosaraju_algorithm.cpp new file mode 100644 index 00000000..5dd0be21 --- /dev/null +++ b/CPP/algorithms/graph_algorithms/kosaraju_algorithm.cpp @@ -0,0 +1,145 @@ +// Kosaraju’s Algorithm — Find Strongly Connected Components (SCCs) +// Problem +// Given a directed graph, find all SCCs (maximal groups of vertices +// where every vertex can reach every other vertex in the group). +// +// Approach +// 1. Perform DFS and store vertices in a stack according to finish times. +// 2. Reverse all edges (transpose the graph). +// 3. Perform DFS on the transposed graph in the order of the stack. +// Each DFS traversal finds one SCC. +// +// Complexity +// Time : O(V + E) — DFS twice, transpose edges +// Space : O(V + E) — adjacency list + visited arrays + recursion stack +// +// Input +// - Number of vertices (V) +// - List of edges {u, v} +// +// Output +// - List of all SCCs + +#include +#include +using namespace std; + +int V; +vector> adj; +vector> adjT; +vector visited; + +// DFS for finish time +void dfs1(int u, vector &order) +{ + visited[u] = true; + for (size_t i = 0; i < adj[u].size(); i++) + { + int v = adj[u][i]; + if (!visited[v]) + dfs1(v, order); + } + order.push_back(u); // finished +} + +// DFS for SCC on transposed graph +void dfs2(int u, vector &component) +{ + visited[u] = true; + component.push_back(u); + for (size_t i = 0; i < adjT[u].size(); i++) + { + int v = adjT[u][i]; + if (!visited[v]) + dfs2(v, component); + } +} + +int main() +{ + ios::sync_with_stdio(false); + cin.tie(nullptr); + + int E; + cin >> V >> E; + adj.assign(V, vector()); + adjT.assign(V, vector()); + + for (int i = 0; i < E; i++) + { + int u, v; + cin >> u >> v; + adj[u].push_back(v); + adjT[v].push_back(u); // transpose edge + } + + vector order; + visited.assign(V, false); + + // Step 1: DFS to get finish times + for (int i = 0; i < V; i++) + if (!visited[i]) + dfs1(i, order); + + // Step 2: DFS on transposed graph + visited.assign(V, false); + vector> sccs; + for (int i = V - 1; i >= 0; i--) + { + int u = order[i]; + if (!visited[u]) + { + vector component; + dfs2(u, component); + sccs.push_back(component); + } + } + + // Output SCCs + cout << "Strongly Connected Components:\n"; + for (size_t i = 0; i < sccs.size(); i++) + { + for (size_t j = 0; j < sccs[i].size(); j++) + cout << sccs[i][j] << " "; + cout << "\n"; + } + + return 0; +} + +/* +Example Input: +5 5 +0 2 +2 1 +1 0 +0 3 +3 4 + +Visualization: +Graph: +0 → 2 → 1 → 0 (cycle) +0 → 3 → 4 + +Step 1: DFS to record finish times +Stack order (top = last finished): [4, 3, 0, 1, 2] + +Step 2: Transpose graph +Edges reversed: +2 → 0 +1 → 2 +0 → 1 +3 → 0 +4 → 3 + +Step 3: DFS on transposed graph using stack order +- Pop 2 → DFS → {0,1,2} (SCC) +- Pop 3 → DFS → {3} (SCC) +- Pop 4 → DFS → {4} (SCC) + +Final SCCs: +{0,1,2}, {3}, {4} + +Time : O(V + E) +Space : O(V + E) +*/