0% found this document useful (0 votes)
10 views

Graph Notes

nice book of seleted graph questions

Uploaded by

HARSH Yadav
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

Graph Notes

nice book of seleted graph questions

Uploaded by

HARSH Yadav
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 41

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];
}

You might also like