struct GraphEdge {
int src, dest, weight;
GraphEdge(int u, int v, int w) : src(u), dest(v), weight(w) {}
};
### Graph Representation: Adjacency Matrix and Adjacency List
// Adjacency Matrix
class GraphMatrix {
public:
vector<vector<int>> adjMatrix;
GraphMatrix(int vertices) : adjMatrix(vertices, vector<int>(vertices, 0)) {}
void addEdge(int u, int v, int weight = 1) {
adjMatrix[u][v] = weight;
// For undirected graph, also add adjMatrix[v][u] = weight;
}
};
// Adjacency List
class GraphList {
public:
vector<vector<pair<int, int>>> adjList;
GraphList(int vertices) : adjList(vertices) {}
void addEdge(int u, int v, int weight = 1) {
adjList[u].push_back({v, weight});
// For undirected graph, also add adjList[v].push_back({u, weight});
}
};
### Depth First Search (DFS)
void dfs(int node, vector<bool>& visited, const vector<vector<int>>& adjList) {
visited[node] = true;
cout << node << " ";
for (const auto& neighbor : adjList[node]) {
if (!visited[neighbor.first]) {
dfs(neighbor.first, visited, adjList);
}
}
}
### Breadth First Search (BFS)
void bfs(int start, const vector<vector<int>>& adjList) {
queue<int> q;
vector<bool> visited(adjList.size(), false);
q.push(start);
visited[start] = true;
while (!q.empty()) {
int node = q.front();
q.pop();
cout << node << " ";
for (const auto& neighbor : adjList[node]) {
if (!visited[neighbor.first]) {
q.push(neighbor.first);
visited[neighbor.first] = true;
}
}
}
}
### Bidirectional Search
bool bidirectionalSearch(const vector<vector<int>>& adjList, int src, int dest) {
if (src == dest) return true;
unordered_set<int> srcSet, destSet;
queue<int> srcQueue, destQueue;
srcQueue.push(src);
destQueue.push(dest);
srcSet.insert(src);
destSet.insert(dest);
while (!srcQueue.empty() && !destQueue.empty()) {
if (bfsStep(adjList, srcQueue, srcSet, destSet)) return true;
if (bfsStep(adjList, destQueue, destSet, srcSet)) return true;
}
return false;
}
bool bfsStep(const vector<vector<int>>& adjList, queue<int>& q, unordered_set<int>&
visited, unordered_set<int>& otherVisited) {
int node = q.front();
q.pop();
for (const auto& neighbor : adjList[node]) {
if (otherVisited.count(neighbor.first)) return true;
if (!visited.count(neighbor.first)) {
visited.insert(neighbor.first);
q.push(neighbor.first);
}
}
return false;
}
### Topological Sorting using Depth First Search (DFS)
void topologicalSortDFS(int node, vector<bool>& visited, stack<int>& s, const
vector<vector<int>>& adjList) {
visited[node] = true;
for (const auto& neighbor : adjList[node]) {
if (!visited[neighbor.first]) {
topologicalSortDFS(neighbor.first, visited, s, adjList);
}
}
s.push(node);
}
vector<int> getTopologicalSortDFS(const vector<vector<int>>& adjList) {
stack<int> s;
vector<bool> visited(adjList.size(), false);
for (int i = 0; i < adjList.size(); ++i) {
if (!visited[i]) {
topologicalSortDFS(i, visited, s, adjList);
}
}
vector<int> result;
while (!s.empty()) {
result.push_back(s.top());
s.pop();
}
return result;
}
### Topological Sort using Breadth First Search (BFS) (Kahn’s Algorithm)
vector<int> topologicalSortBFS(const vector<vector<int>>& adjList) {
vector<int> inDegree(adjList.size(), 0);
for (const auto& neighbors : adjList) {
for (const auto& neighbor : neighbors) {
inDegree[neighbor.first]++;
}
}
queue<int> q;
for (int i = 0; i < inDegree.size(); ++i) {
if (inDegree[i] == 0) {
q.push(i);
}
}
vector<int> result;
while (!q.empty()) {
int node = q.front();
q.pop();
result.push_back(node);
for (const auto& neighbor : adjList[node]) {
if (--inDegree[neighbor.first] == 0) {
q.push(neighbor.first);
}
}
}
if (result.size() != adjList.size()) {
return {}; // Graph has a cycle
}
return result;
}
### Shortest Path using Topological Sort
vector<int> shortestPathTopologicalSort(const vector<vector<pair<int, int>>>&
adjList, int src) {
vector<int> topoOrder = getTopologicalSortDFS(adjList);
vector<int> dist(adjList.size(), INT_MAX);
dist[src] = 0;
for (int node : topoOrder) {
if (dist[node] != INT_MAX) {
for (const auto& neighbor : adjList[node]) {
if (dist[neighbor.first] > dist[node] + neighbor.second) {
dist[neighbor.first] = dist[node] + neighbor.second;
}
}
}
}
return dist;
}
### Find and Print All Paths Between Two Vertices
void findAllPaths(int u, int d, vector<bool>& visited, vector<int>& path, const
vector<vector<int>>& adjList, vector<vector<int>>& paths) {
visited[u] = true;
path.push_back(u);
if (u == d) {
paths.push_back(path);
} else {
for (const auto& neighbor : adjList[u]) {
if (!visited[neighbor.first]) {
findAllPaths(neighbor.first, d, visited, path, adjList, paths);
}
}
}
path.pop_back();
visited[u] = false;
}
vector<vector<int>> getAllPaths(int src, int dest, const vector<vector<int>>&
adjList) {
vector<bool> visited(adjList.size(), false);
vector<int> path;
vector<vector<int>> paths;
findAllPaths(src, dest, visited, path, adjList, paths);
return paths;
}
### Count Paths from Top Left to Bottom Right of a Matrix
int countPaths(int m, int n) {
vector<vector<int>> dp(m, vector<int>(n, 1));
for (int i = 1; i < m; ++i) {
for (int j = 1; j < n; ++j) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
}
### Find if There Exists a Path Between Two Nodes in a Directed Graph
bool hasPathDFS(int u, int d, vector<bool>& visited, const vector<vector<int>>&
adjList) {
if (u == d) return true;
visited[u] = true;
for (const auto& neighbor : adjList[u]) {
if (!visited[neighbor.first] && hasPathDFS(neighbor.first, d, visited,
adjList)) {
return true;
}
}
return false;
}
bool hasPath(int src, int dest, const vector<vector<int>>& adjList) {
vector<bool> visited(adjList.size(), false);
return hasPathDFS(src, dest, visited, adjList);
}
### Dijkstra's Algorithm
vector<int> dijkstra(const vector<vector<pair<int, int>>>& adjList, int src) {
vector<int> dist(adjList.size(), INT_MAX);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>>
pq;
dist[src] = 0;
pq.push({0, src});
while (!pq.empty()) {
int u = pq.top().second;
pq.pop();
for (const auto& neighbor : adjList[u]) {
int v = neighbor.first, weight = neighbor.second;
if (dist[u] + weight < dist[v]) {
dist[v] = dist[u] + weight;
pq.push({dist[v], v});
}
}
}
return dist;
}
### Floyd-Warshall Algorithm
vector<vector<int>> floydWarshall(const vector<vector<int>>& graph) {
int V = graph.size();
vector<vector<int>> dist = graph;
for (int k = 0; k < V; ++k) {
for (int i = 0; i < V; ++i) {
for (int j = 0; j < V; ++j) {
if (dist[i][k] != INT_MAX && dist[k][j] != INT_MAX && dist[i][k] +
dist[k][j] < dist[i][j]) {
dist
[i][j] = dist[i][k] + dist[k][j];
}
}
}
}
return dist;
}
### Bellman-Ford Algorithm
vector<int> bellmanFord(const vector<vector<pair<int, int>>>& edges, int V, int
src) {
vector<int> dist(V, INT_MAX);
dist[src] = 0;
for (int i = 0; i < V - 1; ++i) {
for (const auto& edge : edges) {
int u = edge[0], v = edge[1], weight = edge[2];
if (dist[u] != INT_MAX && dist[u] + weight < dist[v]) {
dist[v] = dist[u] + weight;
}
}
}
for (const auto& edge : edges) {
int u = edge[0], v = edge[1], weight = edge[2];
if (dist[u] != INT_MAX && dist[u] + weight < dist[v]) {
throw runtime_error("Graph contains negative weight cycle");
}
}
return dist;
}
### Shortest Path Faster Algorithm (SPFA)
vector<int> spfa(const vector<vector<pair<int, int>>>& adjList, int src) {
vector<int> dist(adjList.size(), INT_MAX);
vector<bool> inQueue(adjList.size(), false);
queue<int> q;
dist[src] = 0;
q.push(src);
inQueue[src] = true;
while (!q.empty()) {
int u = q.front();
q.pop();
inQueue[u] = false;
for (const auto& neighbor : adjList[u]) {
int v = neighbor.first, weight = neighbor.second;
if (dist[u] + weight < dist[v]) {
dist[v] = dist[u] + weight;
if (!inQueue[v]) {
q.push(v);
inQueue[v] = true;
}
}
}
}
return dist;
}
### Johnson's Algorithm
vector<vector<int>> johnson(const vector<vector<pair<int, int>>>& adjList) {
int V = adjList.size();
vector<vector<int>> adjListCopy = adjList;
adjListCopy.push_back({});
for (int i = 0; i < V; ++i) {
adjListCopy[V].push_back({i, 0});
}
vector<int> h = bellmanFord(adjListCopy, V + 1, V);
vector<vector<int>> newGraph(V, vector<int>(V, INT_MAX));
for (int u = 0; u < V; ++u) {
for (const auto& neighbor : adjList[u]) {
int v = neighbor.first, weight = neighbor.second;
newGraph[u][v] = weight + h[u] - h[v];
}
}
vector<vector<int>> dist(V, vector<int>(V, INT_MAX));
for (int u = 0; u < V; ++u) {
dist[u] = dijkstra(newGraph, u);
for (int v = 0; v < V; ++v) {
if (dist[u][v] != INT_MAX) {
dist[u][v] += h[v] - h[u];
}
}
}
return dist;
}
### Kruskal’s Minimum Spanning Tree Algorithm
class UnionFind {
public:
vector<int> parent, rank;
UnionFind(int n) : parent(n), rank(n, 0) {
iota(parent.begin(), parent.end(), 0);
}
int find(int u) {
if (u != parent[u]) {
parent[u] = find(parent[u]);
}
return parent[u];
}
bool unite(int u, int v) {
int pu = find(u), pv = find(v);
if (pu == pv) return false;
if (rank[pu] < rank[pv]) {
parent[pu] = pv;
} else if (rank[pu] > rank[pv]) {
parent[pv] = pu;
} else {
parent[pv] = pu;
rank[pu]++;
}
return true;
}
};
int kruskalMST(vector<vector<int>>& edges, int V) {
sort(edges.begin(), edges.end(), [](const auto& a, const auto& b) { return a[2]
< b[2]; });
UnionFind uf(V);
int mstWeight = 0;
for (const auto& edge : edges) {
if (uf.unite(edge[0], edge[1])) {
mstWeight += edge[2];
}
}
return mstWeight;
}
### Prim’s Minimum Spanning Tree Algorithm
int primMST(const vector<vector<pair<int, int>>>& adjList) {
int V = adjList.size();
vector<int> key(V, INT_MAX);
vector<bool> inMST(V, false);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>>
pq;
key[0] = 0;
pq.push({0, 0});
int mstWeight = 0;
while (!pq.empty()) {
int u = pq.top().second;
pq.pop();
if (inMST[u]) continue;
inMST[u] = true;
mstWeight += key[u];
for (const auto& neighbor : adjList[u]) {
int v = neighbor.first, weight = neighbor.second;
if (!inMST[v] && weight < key[v]) {
key[v] = weight;
pq.push({key[v], v});
}
}
}
return mstWeight;
}
### Boruvka’s Minimum Spanning Tree Algorithm
int boruvkaMST(const vector<vector<pair<int, int>>>& adjList) {
int V = adjList.size();
UnionFind uf(V);
int mstWeight = 0;
int numTrees = V;
while (numTrees > 1) {
vector<int> cheapest(V, -1);
for (int u = 0; u < V; ++u) {
for (const auto& neighbor : adjList[u]) {
int v = neighbor.first, weight = neighbor.second;
int setU = uf.find(u), setV = uf.find(v);
if (setU != setV) {
if (cheapest[setU] == -1 || adjList[cheapest[setU]][0].second >
weight) {
cheapest[setU] = v;
}
if (cheapest[setV] == -1 || adjList[cheapest[setV]][0].second >
weight) {
cheapest[setV] = u;
}
}
}
}
for (int u = 0; u < V; ++u) {
if (cheapest[u] != -1) {
int v = cheapest[u];
int setU = uf.find(u), setV = uf.find(v);
if (setU != setV) {
mstWeight += adjList[u][v].second;
uf.unite(setU, setV);
numTrees--;
}
}
}
}
return mstWeight;
}
### Reverse Delete Algorithm for MST
int reverseDeleteMST(vector<vector<int>>& edges, int V) {
sort(edges.begin(), edges.end(), [](const auto& a, const auto& b) { return a[2]
> b[2]; });
UnionFind uf(V);
int mstWeight = 0;
for (const auto& edge : edges) {
uf.unite(edge[0], edge[1]);
}
for (const auto& edge : edges) {
int u = edge[0], v = edge[1];
uf = UnionFind(V);
for (const auto& e : edges) {
if (e != edge) {
uf.unite(e[0], e[1]);
}
}
if (uf.find(u) != uf.find(v)) {
mstWeight += edge[2];
}
}
return mstWeight;
}
Here are C++ implementations for the algorithms you mentioned:
### Ford-Fulkerson Algorithm for Maximum Flow
#include <iostream>
#include <vector>
#include <climits>
#include <queue>
#include <cstring>
using namespace std;
bool bfs(vector<vector<int>>& rGraph, int s, int t, vector<int>& parent) {
int V = rGraph.size();
vector<bool> visited(V, false);
queue<int> q;
q.push(s);
visited[s] = true;
parent[s] = -1;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v = 0; v < V; ++v) {
if (!visited[v] && rGraph[u][v] > 0) {
if (v == t) {
parent[v] = u;
return true;
}
q.push(v);
parent[v] = u;
visited[v] = true;
}
}
}
return false;
}
int fordFulkerson(vector<vector<int>>& graph, int s, int t) {
int u, v;
int V = graph.size();
vector<vector<int>> rGraph(V, vector<int>(V));
for (u = 0; u < V; u++)
for (v = 0; v < V; v++)
rGraph[u][v] = graph[u][v];
vector<int> parent(V);
int maxFlow = 0;
while (bfs(rGraph, s, t, parent)) {
int pathFlow = INT_MAX;
for (v = t; v != s; v = parent[v]) {
u = parent[v];
pathFlow = min(pathFlow, rGraph[u][v]);
}
for (v = t; v != s; v = parent[v]) {
u = parent[v];
rGraph[u][v] -= pathFlow;
rGraph[v][u] += pathFlow;
}
maxFlow += pathFlow;
}
return maxFlow;
}
### Dinic's Algorithm for Maximum Flow
#include <iostream>
#include <vector>
#include <climits>
#include <queue>
using namespace std;
class Dinic {
public:
Dinic(int n) : n(n), adj(n), level(n), ptr(n) {}
void addEdge(int u, int v, int cap) {
adj[u].push_back({v, edges.size()});
edges.push_back({u, v, cap});
adj[v].push_back({u, edges.size()});
edges.push_back({v, u, 0});
}
int maxFlow(int s, int t) {
int flow = 0;
while (bfs(s, t)) {
fill(ptr.begin(), ptr.end(), 0);
while (int pushed = dfs(s, t, INT_MAX)) {
flow += pushed;
}
}
return flow;
}
private:
struct Edge {
int u, v, cap, flow = 0;
};
int n;
vector<Edge> edges;
vector<vector<pair<int, int>>> adj;
vector<int> level, ptr;
bool bfs(int s, int t) {
queue<int> q;
q.push(s);
fill(level.begin(), level.end(), -1);
level[s] = 0;
while (!q.empty()) {
int u = q.front();
q.pop();
for (auto& [v, id] : adj[u]) {
if (level[v] == -1 && edges[id].cap > edges[id].flow) {
level[v] = level[u] + 1;
q.push(v);
}
}
}
return level[t] != -1;
}
int dfs(int u, int t, int flow) {
if (u == t) return flow;
for (int& cid = ptr[u]; cid < adj[u].size(); ++cid) {
auto& [v, id] = adj[u][cid];
if (level[v] == level[u] + 1 && edges[id].cap > edges[id].flow) {
int tr = dfs(v, t, min(flow, edges[id].cap - edges[id].flow));
if (tr == 0) continue;
edges[id].flow += tr;
edges[id ^ 1].flow -= tr;
return tr;
}
}
return 0;
}
};
### Edmonds-Karp Algorithm
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;
bool bfs(vector<vector<int>>& rGraph, int s, int t, vector<int>& parent) {
int V = rGraph.size();
vector<bool> visited(V, false);
queue<int> q;
q.push(s);
visited[s] = true;
parent[s] = -1;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v = 0; v < V; ++v) {
if (!visited[v] && rGraph[u][v] > 0) {
if (v == t) {
parent[v] = u;
return true;
}
q.push(v);
parent[v] = u;
visited[v] = true;
}
}
}
return false;
}
int edmondsKarp(vector<vector<int>>& graph, int s, int t) {
int u, v;
int V = graph.size();
vector<vector<int>> rGraph(V, vector<int>(V));
for (u = 0; u < V; u++)
for (v = 0; v < V; v++)
rGraph[u][v] = graph[u][v];
vector<int> parent(V);
int maxFlow = 0;
while (bfs(rGraph, s, t, parent)) {
int pathFlow = INT_MAX;
for (v = t; v != s; v = parent[v]) {
u = parent[v];
pathFlow = min(pathFlow, rGraph[u][v]);
}
for (v = t; v != s; v = parent[v]) {
u = parent[v];
rGraph[u][v] -= pathFlow;
rGraph[v][u] += pathFlow;
}
maxFlow += pathFlow;
}
return maxFlow;
}
### Push-Relabel Algorithm
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
class PushRelabel {
public:
PushRelabel(int n) : n(n), excess(n), height(n), graph(n, vector<int>(n)),
capacity(n, vector<int>(n)) {}
void addEdge(int u, int v, int cap) {
capacity[u][v] = cap;
}
int maxFlow(int s, int t) {
height[s] = n;
excess[s] = INT_MAX;
for (int i = 0; i < n; i++) {
if (i != s) {
push(s, i);
}
}
while (!active.empty()) {
int u = active.front();
active.pop();
if (u != s && u != t) {
discharge(u);
}
}
return excess[t];
}
private:
int n;
vector<vector<int>> capacity;
vector<vector<int>> graph;
vector<int> excess;
vector<int> height;
queue<int> active;
void push(int u, int v) {
int flow = min(excess[u], capacity[u][v] - graph[u][v]);
graph[u][v] += flow;
graph[v][u] -= flow;
excess[u] -= flow;
excess[v] += flow;
if (excess[v] == flow) active.push(v);
}
void relabel(int u) {
int minHeight = INT_MAX;
for (int v = 0; v < n; v++) {
if (capacity[u][v] - graph[u][v] > 0) {
minHeight = min(minHeight, height[v]);
height[u] = minHeight + 1;
}
}
}
void discharge(int u) {
while (excess[u] > 0) {
bool pushed = false;
for (int v = 0; v < n && excess[u] > 0; v++) {
if (capacity[u][v] - graph[u][v] > 0 && height[u] > height[v]) {
push(u, v);
pushed = true;
}
}
if (!pushed) {
relabel(u);
}
}
}
};
### Welsh-Powell Algorithm for Graph Coloring
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int welshPowell(vector<vector<int>>& graph) {
int n = graph.size();
vector<int> colors(n, -1);
vector<int> degree(n);
for (int i = 0; i < n; ++i) {
degree[i] = count(graph[i].begin(), graph[i].end(), 1);
}
vector<int> vertices(n);
iota(vertices.begin(), vertices.end(), 0);
sort(vertices.begin(), vertices.end(), [&](int a, int b) {
return degree[a] > degree[b];
});
int
color = 0;
for (int i : vertices) {
if (colors[i] == -1) {
colors[i] = color;
for (int j : vertices) {
if (colors[j] == -1 && graph[i][j] == 0) {
bool canColor = true;
for (int k = 0; k < n; ++k) {
if (graph[j][k] == 1 && colors[k] == color) {
canColor = false;
break;
}
}
if (canColor) colors[j] = color;
}
}
color++;
}
}
return color;
}
### Wigderson Graph Coloring Algorithm
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int wigdersonColoring(vector<vector<int>>& graph) {
int n = graph.size();
vector<int> colors(n, -1);
vector<int> degree(n);
for (int i = 0; i < n; ++i) {
degree[i] = count(graph[i].begin(), graph[i].end(), 1);
}
vector<int> vertices(n);
iota(vertices.begin(), vertices.end(), 0);
sort(vertices.begin(), vertices.end(), [&](int a, int b) {
return degree[a] < degree[b];
});
int maxDegree = *max_element(degree.begin(), degree.end());
int maxColors = maxDegree + 1;
for (int v : vertices) {
vector<bool> available(maxColors, true);
for (int u = 0; u < n; ++u) {
if (graph[v][u] && colors[u] != -1) {
available[colors[u]] = false;
}
}
for (int c = 0; c < maxColors; ++c) {
if (available[c]) {
colors[v] = c;
break;
}
}
}
return *max_element(colors.begin(), colors.end()) + 1;
}
### Greedy Graph Coloring Algorithm
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int greedyColoring(vector<vector<int>>& graph) {
int n = graph.size();
vector<int> result(n, -1);
vector<bool> available(n, true);
result[0] = 0;
for (int u = 1; u < n; u++) {
fill(available.begin(), available.end(), true);
for (int i = 0; i < n; ++i) {
if (graph[u][i] && result[i] != -1) {
available[result[i]] = false;
}
}
int cr;
for (cr = 0; cr < n; cr++) {
if (available[cr]) break;
}
result[u] = cr;
}
return *max_element(result.begin(), result.end()) + 1;
}
### Bipartite Checking using Graph Coloring (BFS)
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
bool isBipartite(vector<vector<int>>& graph) {
int n = graph.size();
vector<int> color(n, -1);
queue<int> q;
for (int i = 0; i < n; ++i) {
if (color[i] == -1) {
color[i] = 1;
q.push(i);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v = 0; v < n; ++v) {
if (graph[u][v] && color[v] == -1) {
color[v] = 1 - color[u];
q.push(v);
} else if (graph[u][v] && color[v] == color[u]) {
return false;
}
}
}
}
}
return true;
}
### Hopcroft-Karp Algorithm
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
class HopcroftKarp {
public:
HopcroftKarp(int n, int m) : n(n), m(m), pairU(n + 1, 0), pairV(m + 1, 0),
dist(n + 1) {}
void addEdge(int u, int v) {
adj[u].push_back(v);
}
int maxMatching() {
int matching = 0;
while (bfs()) {
for (int u = 1; u <= n; u++) {
if (pairU[u] == 0 && dfs(u)) {
matching++;
}
}
}
return matching;
}
private:
int n, m;
vector<int> pairU, pairV, dist;
vector<vector<int>> adj;
bool bfs() {
queue<int> q;
for (int u = 1; u <= n; u++) {
if (pairU[u] == 0) {
dist[u] = 0;
q.push(u);
} else {
dist[u] = INT_MAX;
}
}
dist[0] = INT_MAX;
while (!q.empty()) {
int u = q.front();
q.pop();
if (dist[u] < dist[0]) {
for (int v : adj[u]) {
if (dist[pairV[v]] == INT_MAX) {
dist[pairV[v]] = dist[u] + 1;
q.push(pairV[v]);
}
}
}
}
return dist[0] != INT_MAX;
}
bool dfs(int u) {
if (u != 0) {
for (int v : adj[u]) {
if (dist[pairV[v]] == dist[u] + 1 && dfs(pairV[v])) {
pairV[v] = u;
pairU[u] = v;
return true;
}
}
dist[u] = INT_MAX;
return false;
}
return true;
}
};
### Hungarian Maximum Matching Algorithm
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int INF = 1e9;
int hungarianAlgorithm(vector<vector<int>>& cost) {
int n = cost.size();
vector<int> u(n + 1), v(n + 1), p(n + 1), way(n + 1);
for (int i = 1; i <= n; i++) {
p[0] = i;
int j0 = 0;
vector<int> minv(n + 1, INF);
vector<bool> used(n + 1, false);
do {
used[j0] = true;
int i0 = p[j0], delta = INF, j1;
for (int j = 1; j <= n; j++) {
if (!used[j]) {
int cur = cost[i0 - 1][j - 1] - u[i0] - v[j];
if (cur < minv[j]) {
minv[j] = cur;
way[j] = j0;
}
if (minv[j] < delta) {
delta = minv[j];
j1 = j;
}
}
}
for (int j = 0; j <= n; j++) {
if (used[j]) {
u[p[j]] += delta;
v[j] -= delta;
} else {
minv[j] -= delta;
}
}
j0 = j1;
} while (p[j0] != 0);
do {
int j1 = way[j0];
p[j0] = p[j1];
j0 = j1;
} while (j0 != 0);
}
return -v[0];
}
### Blossom Maximum Matching Algorithm (Edmonds’ Algorithm)
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
class Blossom {
public:
Blossom(int n) : n(n), graph(n, vector<int>(n, 0)), match(n, -1), parent(n),
base(n), q(n) {}
void addEdge(int u, int v) {
graph[u][v] = graph[v][u] = 1;
}
int maximumMatching() {
int matchCount = 0;
for (int i = 0; i < n; ++i) {
if (match[i] == -1) {
if (augment(i)) matchCount++;
}
}
return matchCount;
}
private:
int n;
vector<vector<int>> graph;
vector<int> match, parent, base, q;
vector<bool> blossom;
int findCommonAncestor(int u, int v) {
vector<bool> visited(n, false);
while (true) {
u = base[u];
visited[u] = true;
if (match[u] == -1) break;
u = parent[match[u]];
}
while (true) {
v = base[v];
if (visited[v]) return v;
v = parent[match[v]];
}
}
void markPath(int u, int b, int child) {
while (base[u] != b) {
blossom[base[u]] =
blossom[base[match[u]]] = true;
parent[u] = child;
child = match[u];
u = parent[child];
}
}
int findAugmentingPath(int start) {
fill(parent.begin(), parent.end(), -1);
fill(blossom.begin(), blossom.end(), false);
for (int i = 0; i < n; ++i) base[i] = i;
int qh = 0, qt = 0;
q[qt++] = start;
while (qh < qt) {
int u = q[qh++];
for (int v = 0; v < n; ++v) {
if (graph[u][v] && base[u] != base[v] && match[u] != v) {
if (v == start || (match[v] != -1 && parent[match[v]] != -1)) {
int b = findCommonAncestor(u, v);
markPath(u, b, v);
markPath(v, b, u);
for (int i = 0; i < n; ++i) {
if (blossom[base[i]]) {
base[i] = b;
if (!blossom[i]) q[qt++] = i;
}
}
} else if (parent[v] == -1) {
parent[v] = u;
if (match[v] == -1) return v;
v = match[v];
q[qt++] = v;
}
}
}
}
return -1;
}
bool augment(int start) {
int v = findAugmentingPath(start);
if (v == -1) return false;
while (v != -1) {
int pv = parent[v], nv = match[pv];
match[v] = pv;
match[pv] = v;
v = nv;
}
return true;
}
};
### Gale-Shapley Algorithm for Stable Matching
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
void galeShapley(int n, vector<vector<int>>& menPref, vector<vector<int>>&
womenPref) {
vector<int> womenPartner(n, -1);
vector<bool> menFree(n, false);
vector<int> menNext(n, 0);
queue<int> freeMen;
for (int i = 0; i < n; ++i) freeMen.push(i);
while (!freeMen.empty()) {
int m = freeMen.front();
freeMen.pop();
int w = menPref[m][menNext[m]];
menNext[m]++;
if (womenPartner[w] == -1) {
womenPartner[w] = m;
} else {
int m1 = womenPartner[w];
int indexM = find(womenPref[w].begin(), womenPref[w].end(), m) -
womenPref[w].begin();
int indexM1 = find(womenPref[w].begin(), womenPref[w].end(), m1) -
womenPref[w].begin();
if (indexM < indexM1) {
womenPartner[w] = m;
freeMen.push(m1);
} else {
freeMen.push(m);
}
}
}
for (int i = 0; i < n; ++i) {
cout << "Woman " << i << " is matched with Man " << womenPartner[i] <<
endl;
}
}
### Stable Roommates Problem (Irving's Algorithm)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void stableRoommates(int n, vector<vector<int>>& pref) {
vector<int> partner(n, -1);
vector<int> next(n, 0);
vector<vector<int>> proposal(n, vector<int>(n, -1));
vector<vector<int>> invPref(n, vector<int>(n));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
invPref[i][pref[i][j]] = j;
for (int i = 0; i < n; ++i) {
while (next[i] < n && partner[i] == -1) {
int p = pref[i][next[i]++];
if (partner[p] == -1) {
partner[i] = p;
partner[p] = i;
} else if (invPref[p][i] < invPref[p][partner[p]]) {
partner[partner[p]] = -1;
partner[i] = p;
partner[p] = i;
}
}
}
for (int i = 0; i < n; ++i) {
cout << "Person " << i << " is matched with " << partner[i] << endl;
}
}
### Hospital Residents Problem
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
void hospitalResidents(int n, int m, vector<vector<int>>& hospitals,
vector<vector<int>>& residents) {
vector<int> residentToHospital(n, -1);
vector<int> hospitalCapacity(m, 1);
vector<queue<int>> hospitalPrefs(m);
vector<vector<int>> residentPrefs(n, vector<int>(m, -1));
vector<vector<int>> hospitalRanks(m, vector<int>(n, -1));
for (int i = 0; i < m; ++i) {
for (int j = 0; j < hospitals[i].size(); ++j) {
hospitalPrefs[i].push(hospitals[i][j]);
hospitalRanks[i][hospitals[i][j]] = j;
}
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < residents[i].size(); ++j) {
residentPrefs[i][j] = residents[i][j];
}
}
bool stable = false;
while (!stable) {
stable = true;
for (int i = 0; i < m; ++i) {
if (hospitalCapacity[i] > 0 && !hospitalPrefs[i].empty()) {
int r = hospitalPrefs[i].front();
hospitalPrefs[i].pop();
if (residentToHospital[r] == -1) {
residentToHospital[r] = i;
hospitalCapacity[i]--;
} else {
int currentHospital = residentToHospital[r];
if (hospitalRanks[currentHospital][r] > hospitalRanks[i][r]) {
residentToHospital[r] = i;
hospitalCapacity[i]--;
hospitalCapacity[currentHospital]++;
stable = false;
}
}
}
}
}
for (int i = 0; i < n; ++i) {
cout << "Resident " << i << " is assigned to Hospital " <<
residentToHospital[i] << endl;
}
}
Certainly! Here are the C++ functions for the algorithms you requested:
### Finding Cut Edges in a Graph (Bridge Finding Algorithm)
#include <iostream>
#include <vector>
using namespace std;
class BridgesFinder {
public:
BridgesFinder(int n) : n(n), id(0), bridges(0), visited(n, false), low(n),
ids(n), adj(n) {}
void addEdge(int u, int v) {
adj[u].push_back(v);
adj[v].push_back(u);
}
vector<pair<int, int>> findBridges() {
for (int i = 0; i < n; ++i) {
if (!visited[i]) {
dfs(i, -1);
}
}
return bridges;
}
private:
int n, id;
vector<bool> visited;
vector<int> low, ids;
vector<vector<int>> adj;
vector<pair<int, int>> bridges;
void dfs(int at, int parent) {
visited[at] = true;
low[at] = ids[at] = ++id;
for (int to : adj[at]) {
if (to == parent) continue;
if (!visited[to]) {
dfs(to, at);
low[at] = min(low[at], low[to]);
if (ids[at] < low[to]) {
bridges.push_back({at, to});
}
} else {
low[at] = min(low[at], ids[to]);
}
}
}
};
### Finding Articulation Points in a Graph
#include <iostream>
#include <vector>
using namespace std;
class ArticulationPointsFinder {
public:
ArticulationPointsFinder(int n) : n(n), id(0), rootChildren(0), visited(n,
false), articulationPoints(n), ids(n), low(n), adj(n) {}
void addEdge(int u, int v) {
adj[u].push_back(v);
adj[v].push_back(u);
}
vector<int> findArticulationPoints() {
for (int i = 0; i < n; ++i) {
if (!visited[i]) {
rootChildren = 0;
dfs(i, i);
if (rootChildren > 1) articulationPoints[i] = true;
}
}
return articulationPoints;
}
private:
int n, id, rootChildren;
vector<bool> visited, articulationPoints;
vector<int> ids, low;
vector<vector<int>> adj;
void dfs(int at, int parent) {
visited[at] = true;
ids[at] = low[at] = ++id;
for (int to : adj[at]) {
if (to == parent) continue;
if (!visited[to]) {
dfs(to, at);
low[at] = min(low[at], low[to]);
if (ids[at] <= low[to] && !(parent == at && rootChildren++ == 0)) {
articulationPoints[at] = true;
}
} else {
low[at] = min(low[at], ids[to]);
}
}
}
};
### Tarjan's Algorithm for Strongly Connected Components (SCCs)
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
class TarjansSCC {
public:
TarjansSCC(int n) : n(n), id(0), ids(n, -1), low(n, 0), onStack(n, false),
sccCount(0), graph(n) {}
void addEdge(int u, int v) {
graph[u].push_back(v);
}
vector<vector<int>> findSCCs() {
for (int i = 0; i < n; ++i) {
if (ids[i] == -1) {
dfs(i);
}
}
return sccs;
}
private:
int n, id, sccCount;
vector<int> ids, low;
vector<bool> onStack;
stack<int> st;
vector<vector<int>> graph, sccs;
void dfs(int at) {
st.push(at);
onStack[at] = true;
ids[at] = low[at] = id++;
for (int to : graph[at]) {
if (ids[to] == -1) {
dfs(to);
low[at] = min(low[at], low[to]);
} else if (onStack[to]) {
low[at] = min(low[at], ids[to]);
}
}
if (ids[at] == low[at]) {
sccs.push_back(vector<int>());
while (true) {
int node = st.top();
st.pop();
onStack[node] = false;
sccs[sccCount].push_back(node);
if (node == at) break;
}
sccCount++;
}
}
};
### Transitive Closure of a Graph using Floyd Warshall Algorithm
#include <iostream>
#include <vector>
using namespace std;
vector<vector<bool>> transitiveClosureFloydWarshall(vector<vector<int>>& graph) {
int n = graph.size();
vector<vector<bool>> reach(n, vector<bool>(n, false));
// Initialize reachability matrix
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (i == j || graph[i][j] != 0) {
reach[i][j] = true;
}
}
}
// Floyd Warshall Algorithm to find transitive closure
for (int k = 0; k < n; ++k) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (!reach[i][j] && reach[i][k] && reach[k][j]) {
reach[i][j] = true;
}
}
}
}
return reach;
}
### Travelling Salesman Problem (Brute Force Approach)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int INF = 1e9;
int tspBruteForce(vector<vector<int>>& graph) {
int n = graph.size();
vector<int> vertex;
for (int i = 1; i < n; ++i) {
vertex.push_back(i);
}
int minPath = INF;
do {
int currentPathWeight = 0;
int k = 0;
for (int i = 0; i < vertex.size(); ++i) {
currentPathWeight += graph[k][vertex[i]];
k = vertex[i];
}
currentPathWeight += graph[k][0]; // Return to the starting vertex
minPath = min(minPath, currentPathWeight);
} while (next_permutation(vertex.begin(), vertex.end()));
return minPath;
}
Certainly! Here are the C++ implementations for the algorithms you requested:
### Transitive Closure of a Graph using Graph Powering
#include <iostream>
#include <vector>
using namespace std;
vector<vector<bool>> transitiveClosureGraphPowering(vector<vector<int>>& graph) {
int n = graph.size();
vector<vector<bool>> reach(n, vector<bool>(n, false));
// Initialize reachability matrix
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (i == j || graph[i][j] != 0) {
reach[i][j] = true;
}
}
}
// Graph powering technique for transitive closure
for (int k = 1; k < n; k *= 2) {
vector<vector<bool>> temp(n, vector<bool>(n, false));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
for (int x = 0; x < n; ++x) {
if (reach[i][x] && reach[x][j]) {
temp[i][j] = true;
break;
}
}
}
}
reach = temp;
}
return reach;
}
### Travelling Salesman Problem (Brute Force Approach)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int INF = 1e9;
int tspBruteForce(vector<vector<int>>& graph) {
int n = graph.size();
vector<int> vertex;
for (int i = 1; i < n; ++i) {
vertex.push_back(i);
}
int minPath = INF;
do {
int currentPathWeight = 0;
int k = 0;
for (int i = 0; i < vertex.size(); ++i) {
currentPathWeight += graph[k][vertex[i]];
k = vertex[i];
}
currentPathWeight += graph[k][0]; // Return to the starting vertex
minPath = min(minPath, currentPathWeight);
} while (next_permutation(vertex.begin(), vertex.end()));
return minPath;
}
### Travelling Salesman Problem (Bitmasking and Dynamic Programming)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int INF = 1e9;
int tspDPBitmask(int mask, int pos, vector<vector<int>>& graph,
vector<vector<int>>& dp) {
int n = graph.size();
if (mask == (1 << n) - 1) {
return graph[pos][0]; // Return to the starting vertex
}
if (dp[mask][pos] != -1) {
return dp[mask][pos];
}
int minCost = INF;
for (int city = 0; city < n; ++city) {
if ((mask & (1 << city)) == 0) { // If city 'city' is not visited
int newCost = graph[pos][city] + tspDPBitmask(mask | (1 << city), city,
graph, dp);
minCost = min(minCost, newCost);
}
}
return dp[mask][pos] = minCost;
}
int tspDynamicProgramming(vector<vector<int>>& graph) {
int n = graph.size();
vector<vector<int>> dp(1 << n, vector<int>(n, -1));
return tspDPBitmask(1, 0, graph, dp);
}
### Travelling Salesman Problem using Branch and Bound Approach
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int INF = 1e9;
struct Node {
int level, cost, vertex;
vector<bool> visited;
};
struct comp {
bool operator()(const Node& a, const Node& b) {
return a.cost > b.cost;
}
};
int tspBranchAndBound(vector<vector<int>>& graph) {
int n = graph.size();
priority_queue<Node, vector<Node>, comp> pq;
Node root = {0, 0, 0, vector<bool>(n, false)};
root.visited[0] = true;
pq.push(root);
while (!pq.empty()) {
Node u = pq.top();
pq.pop();
if (u.level == n - 1) {
if (graph[u.vertex][0] != 0) { // Return to the starting vertex
return u.cost + graph[u.vertex][0];
}
}
for (int v = 0; v < n; ++v) {
if (graph[u.vertex][v] != 0 && !u.visited[v]) {
Node child = {u.level + 1, u.cost + graph[u.vertex][v], v,
u.visited};
child.visited[v] = true;
pq.push(child);
}
}
}
return INF;
}
### Approximation Algorithm for Travelling Salesman Problem (Nearest Neighbor
Algorithm)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int INF = 1e9;
int tspNearestNeighbor(vector<vector<int>>& graph) {
int n = graph.size();
vector<bool> visited(n, false);
visited[0] = true;
int totalCost = 0;
int current = 0;
for (int i = 0; i < n - 1; ++i) {
int next = -1;
int minCost = INF;
for (int j = 0; j < n; ++j) {
if (!visited[j] && graph[current][j] < minCost) {
minCost = graph[current][j];
next = j;
}
}
visited[next] = true;
totalCost += minCost;
current = next;
}
totalCost += graph[current][0]; // Return to the starting vertex
return totalCost;
}
### Algorithm to Find All Bridges in a Graph
#include <iostream>
#include <vector>
using namespace std;
class BridgesFinder {
public:
BridgesFinder(int n) : n(n), id(0), bridges(0), visited(n, false), low(n),
ids(n), adj(n) {}
void addEdge(int u, int v) {
adj[u].push_back(v);
adj[v].push_back(u);
}
vector<pair<int, int>> findBridges() {
for (int i = 0; i < n; ++i) {
if (!visited[i]) {
dfs(i, -1);
}
}
return bridges;
}
private:
int n, id;
vector<bool> visited;
vector<int> low, ids;
vector<vector<int>> adj;
vector<pair<int, int>> bridges;
void dfs(int at, int parent) {
visited[at] = true;
low[at] = ids[at] = ++id;
for (int to : adj[at]) {
if (to == parent) continue;
if (!visited[to]) {
dfs(to, at);
low[at] = min(low[at], low[to]);
if (ids[at] < low[to]) {
bridges.push_back({at, to});
}
} else {
low[at] = min(low[at], ids[to]);
}
}
}
};
### Algorithm to Find Level of Each Node from Root Node (Breadth-First Search)
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
vector<int> findLevelsBFS(int n, vector<vector<int>>& adj, int root) {
vector<int> levels(n, -1);
queue<int> q;
q.push(root);
levels[root] = 0;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v : adj[u]) {
if (levels[v] == -1) {
levels[v] = levels[u] + 1;
q.push(v);
}
}
}
return levels;
}
### Finding Nodes at Distance K from a Given Node (Breadth-First Search)
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
vector<int> findNodesAtDistanceK(int n, vector<vector<int>>& adj, int start, int k)
{
vector<int> nodesAtDistanceK;
vector<bool> visited(n, false);
queue<int> q;
q.push(start);
visited[start] = true;
int currentLevel = 0;
while (!q.empty()) {
int size = q.size();
for (int i = 0; i < size; ++i) {
int u = q.front();
q.pop();
if (currentLevel == k) {
nodesAtDistanceK.push_back(u);
}
for (int v : adj[u]) {
if (!visited[v]) {
visited[v] = true;
q.push(v);
}
}
}
currentLevel++;
if (currentLevel > k) break;
}
return nodesAtDistanceK;
}
Here are the C++ implementations for the algorithms you requested:
### Minimum Number of Nodes to be Removed such that No Subtree has More than K
Nodes
#include <iostream>
#include <vector>
using namespace std;
int removeNodesToMaintainSubtreeSize(vector<vector<int>>& tree, vector<int>&
subtreeSize, int currentNode, int k, int& removedNodes) {
int totalNodes = 1; // Including current node
for (int child : tree[currentNode]) {
totalNodes += removeNodesToMaintainSubtreeSize(tree, subtreeSize, child, k,
removedNodes);
}
subtreeSize[currentNode] = totalNodes;
if (subtreeSize[currentNode] <= k) {
return totalNodes;
} else {
removedNodes += subtreeSize[currentNode] - k;
return k; // Node reduced to k size
}
}
int minNodesToRemoveToMaintainSubtreeSize(vector<vector<int>>& tree, int n, int k)
{
vector<int> subtreeSize(n + 1, 0); // Size of subtree rooted at each node
int removedNodes = 0;
removeNodesToMaintainSubtreeSize(tree, subtreeSize, 1, k, removedNodes); //
Root node is 1
return removedNodes;
}
### Finding Diameter of a Tree using Height of Each Node
#include <iostream>
#include <vector>
using namespace std;
void dfs(vector<vector<int>>& tree, vector<int>& height, int node, int parent) {
for (int neighbor : tree[node]) {
if (neighbor != parent) {
height[neighbor] = height[node] + 1;
dfs(tree, height, neighbor, node);
}
}
}
int diameterOfTree(vector<vector<int>>& tree, int n) {
vector<int> height(n + 1, 0);
// Perform DFS from any node (say node 1)
dfs(tree, height, 1, -1);
// Find farthest node from the root
int farthestNode = 1;
for (int i = 2; i <= n; ++i) {
if (height[i] > height[farthestNode]) {
farthestNode = i;
}
}
// Reset heights and perform DFS from the farthest node
height.assign(n + 1, 0);
dfs(tree, height, farthestNode, -1);
// Find maximum height (diameter)
int diameter = 0;
for (int i = 1; i <= n; ++i) {
diameter = max(diameter, height[i]);
}
return diameter;
}
### Hamiltonian Path in a Graph
#include <iostream>
#include <vector>
using namespace std;
bool hamiltonianPathUtil(vector<vector<int>>& graph, vector<int>& path,
vector<bool>& visited, int pos, int n) {
if (pos == n) {
return true;
}
for (int v : graph[path[pos - 1]]) {
if (!visited[v]) {
visited[v] = true;
path[pos] = v;
if (hamiltonianPathUtil(graph, path, visited, pos + 1, n)) {
return true;
}
visited[v] = false;
}
}
return false;
}
bool hamiltonianPath(vector<vector<int>>& graph, int n) {
vector<int> path(n, -1);
vector<bool> visited(n, false);
// Try different starting points
for (int i = 0; i < n; ++i) {
path[0] = i;
visited[i] = true;
if (hamiltonianPathUtil(graph, path, visited, 1, n)) {
return true;
}
visited[i] = false;
}
return false;
}
### Hamiltonian Cycle in a Graph
#include <iostream>
#include <vector>
using namespace std;
bool hamiltonianCycleUtil(vector<vector<int>>& graph, vector<int>& path,
vector<bool>& visited, int pos, int n) {
if (pos == n) {
// Check if there is an edge from the last vertex to the first vertex
if (graph[path[pos - 1]][path[0]] == 1) {
return true;
} else {
return false;
}
}
for (int v : graph[path[pos - 1]]) {
if (!visited[v]) {
visited[v] = true;
path[pos] = v;
if (hamiltonianCycleUtil(graph, path, visited, pos + 1, n)) {
return true;
}
visited[v] = false;
}
}
return false;
}
bool hamiltonianCycle(vector<vector<int>>& graph, int n) {
vector<int> path(n, -1);
vector<bool> visited(n, false);
// Start from vertex 0 and try different paths
path[0] = 0;
visited[0] = true;
if (hamiltonianCycleUtil(graph, path, visited, 1, n)) {
return true;
}
return false;
}
### Finding Mother Vertex in a Graph
#include <iostream>
#include <vector>
using namespace std;
void dfs(vector<vector<int>>& graph, vector<bool>& visited, int v) {
visited[v] = true;
for (int u : graph[v]) {
if (!visited[u]) {
dfs(graph, visited, u);
}
}
}
int findMotherVertex(vector<vector<int>>& graph, int n) {
vector<bool> visited(n, false);
int lastVisited = 0;
// Perform DFS to find the last finished vertex
for (int i = 0; i < n; ++i) {
if (!visited[i]) {
dfs(graph, visited, i);
lastVisited = i;
}
}
// Reset visited array and perform DFS from the last finished vertex
visited.assign(n, false);
dfs(graph, visited, lastVisited);
// Check if all vertices are visited from the last finished vertex
for (int i = 0; i < n; ++i) {
if (!visited[i]) {
return -1; // No mother vertex
}
}
return lastVisited;
}
### Transpose of a Graph
#include <iostream>
#include <vector>
using namespace std;
vector<vector<int>> transposeGraph(vector<vector<int>>& graph, int n) {
vector<vector<int>> transpose(n);
for (int i = 0; i < n; ++i) {
for (int j : graph[i]) {
transpose[j].push_back(i);
}
}
return transpose;
}
### Farach Colton and Bender Algorithm to Solve LCA
#include <iostream>
#include <vector>
using namespace std;
const int MAXN = 100005; // Adjust according to the problem constraints
vector<int> adj[MAXN];
int parent[MAXN][20]; // Sparse table for storing ancestors up to 2^20
void dfs(int v, int p) {
parent[v][0] = p;
for (int i = 1; i < 20; ++i) {
parent[v][i] = parent[parent[v][i - 1]][i - 1];
}
for (int u : adj[v]) {
if (u != p) {
dfs(u, v);
}
}
}
int lca(int u, int v) {
if (depth[u] < depth[v]) {
swap(u, v);
}
for (int i = 19; i >= 0; --i) {
if (depth[u] - (1 << i) >= depth[v]) {
u = parent[u][i];
}
}
if (u == v) {
return u;
}
for (int i = 19; i >= 0; --i) {
if (parent[u][i] != parent[v][i]) {
u = parent[u][i];
v = parent[v][i];
}
}
return parent[u][0];
}
### Solving Vertex Cover Problem
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int vertexCover(vector<vector<int>>& graph, int n) {
vector<bool> visited(n, false);
int cover = 0;
for (int i = 0; i < n; ++i) {
if (!visited[i]) {
for (int j : graph[i]) {
if (!visited[j]) {
visited[i] = true;
visited[j] = true;
++cover;
break;
}
}
}
}
return cover;
}
### Clique in Graphs
#include <iostream>
#include <vector>
using namespace std;
int findMaximalClique(vector<vector<int>>& graph, int n) {
vector<int> clique(n, 0); // Size of the maximal clique containing each vertex
int maxCliqueSize = 0;
for (int v = n - 1; v >= 0; --v) {
vector<int> candidates;
for (int u = v + 1; u < n; ++u) {
if (graph[v][u]) {
candidates.push_back(u);
}
}
int maxCliqueEndingAtV =
0;
for (int u : candidates) {
maxCliqueEndingAtV = max(maxCliqueEndingAtV, clique[u]);
}
clique[v] = maxCliqueEndingAtV + 1;
maxCliqueSize = max(maxCliqueSize, clique[v]);
}
return maxCliqueSize;
}
### Centroid Decomposition of a Tree
#include <iostream>
#include <vector>
using namespace std;
const int MAXN = 100005; // Adjust according to the problem constraints
vector<int> centroidDecomposition(vector<vector<int>>& tree, int n) {
vector<int> centroid(n);
vector<bool> visited(n, false);
vector<int> subtreeSize(n);
function<void(int, int)> dfsSubtreeSize = [&](int node, int parent) {
subtreeSize[node] = 1;
for (int child : tree[node]) {
if (child != parent && !visited[child]) {
dfsSubtreeSize(child, node);
subtreeSize[node] += subtreeSize[child];
}
}
};
function<int(int, int)> findCentroid = [&](int node, int parent) {
for (int child : tree[node]) {
if (child != parent && !visited[child] && subtreeSize[child] > n / 2) {
return findCentroid(child, node);
}
}
return node;
};
function<void(int, int)> decompose = [&](int node, int parent) {
dfsSubtreeSize(node, -1);
int centroidNode = findCentroid(node, -1);
visited[centroidNode] = true;
centroid[parent] = centroidNode;
for (int child : tree[centroidNode]) {
if (!visited[child]) {
decompose(child, centroidNode);
}
}
};
decompose(0, -1); // Start decomposition from node 0
return centroid;
}
### Karp's Minimum Mean Cycle Algorithm
#include <iostream>
#include <vector>
using namespace std;
const int INF = 1e9;
struct Edge {
int u, v, weight;
};
int minMeanCycle(vector<Edge>& edges, int n) {
vector<int> dist(n, INF);
dist[0] = 0;
for (int i = 0; i < n - 1; ++i) {
for (Edge& edge : edges) {
if (dist[edge.u] != INF && dist[edge.u] + edge.weight < dist[edge.v]) {
dist[edge.v] = dist[edge.u] + edge.weight;
}
}
}
int minMean = INF;
for (Edge& edge : edges) {
if (dist[edge.u] != INF && dist[edge.u] + edge.weight < dist[edge.v]) {
minMean = min(minMean, (dist[edge.v] - dist[edge.u] + edge.weight));
}
}
return minMean;
}
### Eulerian Tour in a Graph (Fleury's Algorithm)
#include <iostream>
#include <vector>
using namespace std;
void dfs(int v, vector<vector<int>>& adj, vector<bool>& visited, vector<int>&
eulerianTour) {
visited[v] = true;
eulerianTour.push_back(v);
for (int u : adj[v]) {
if (!visited[u]) {
dfs(u, adj, visited, eulerianTour);
eulerianTour.push_back(v); // backtrack to v after visiting u
}
}
}
vector<int> findEulerianTour(vector<vector<int>>& adj, int n) {
vector<int> eulerianTour;
vector<bool> visited(n, false);
// Find a starting vertex with non-zero degree
int startVertex = 0;
for (int i = 0; i < n; ++i) {
if (adj[i].size() > 0) {
startVertex = i;
break;
}
}
dfs(startVertex, adj, visited, eulerianTour);
return eulerianTour;
}
### Number of Paths with K Edges using Dynamic Programming and Divide and Conquer
#include <iostream>
#include <vector>
using namespace std;
int countPathsKEdges(vector<vector<int>>& graph, int src, int dest, int k) {
int V = graph.size();
vector<vector<int>> dp(k + 1, vector<int>(V, 0));
dp[0][src] = 1; // Base case: 0 edges path from src to src is 1
for (int e = 1; e <= k; ++e) {
for (int u = 0; u < V; ++u) {
for (int v = 0; v < V; ++v) {
if (graph[u][v]) {
dp[e][v] += dp[e - 1][u];
}
}
}
}
return dp[k][dest];
}
### Shortest Path with K Edges using Dynamic Programming
#include <iostream>
#include <vector>
using namespace std;
const int INF = 1e9;
int shortestPathKEdges(vector<vector<int>>& graph, int src, int dest, int k) {
int V = graph.size();
vector<vector<int>> dp(k + 1, vector<int>(V, INF));
dp[0][src] = 0; // Base case: 0 edges path from src to src is 0
for (int e = 1; e <= k; ++e) {
for (int u = 0; u < V; ++u) {
for (int v = 0; v < V; ++v) {
if (graph[u][v] != INF) {
dp[e][v] = min(dp[e][v], dp[e - 1][u] + graph[u][v]);
}
}
}
}
return dp[k][dest];
}