Graph Notes
Graph Notes
// Adjacency Matrix
class GraphMatrix {
public:
vector<vector<int>> adjMatrix;
GraphMatrix(int vertices) : adjMatrix(vertices, vector<int>(vertices, 0)) {}
// Adjacency List
class GraphList {
public:
vector<vector<pair<int, int>>> adjList;
GraphList(int vertices) : adjList(vertices) {}
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;
}
}
}
}
### Topological Sort using Breadth First Search (BFS) (Kahn’s Algorithm)
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;
}
### Find if There Exists a Path Between Two Nodes in a Directed Graph
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;
}
dist[src] = 0;
q.push(src);
inQueue[src] = true;
while (!q.empty()) {
int u = q.front();
q.pop();
inQueue[u] = false;
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];
}
while (!pq.empty()) {
int u = pq.top().second;
pq.pop();
if (inMST[u]) continue;
inMST[u] = true;
mstWeight += key[u];
#include <iostream>
#include <vector>
#include <climits>
#include <queue>
#include <cstring>
while (!q.empty()) {
int u = q.front();
q.pop();
vector<int> parent(V);
int maxFlow = 0;
for (v = t; v != s; v = parent[v]) {
u = parent[v];
rGraph[u][v] -= pathFlow;
rGraph[v][u] += pathFlow;
}
maxFlow += pathFlow;
}
return maxFlow;
}
#include <iostream>
#include <vector>
#include <climits>
#include <queue>
class Dinic {
public:
Dinic(int n) : n(n), adj(n), level(n), ptr(n) {}
private:
struct Edge {
int u, v, cap, flow = 0;
};
int n;
vector<Edge> edges;
vector<vector<pair<int, int>>> adj;
vector<int> level, ptr;
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;
}
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
while (!q.empty()) {
int u = q.front();
q.pop();
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;
}
#include <iostream>
#include <vector>
#include <climits>
class PushRelabel {
public:
PushRelabel(int n) : n(n), excess(n), height(n), graph(n, vector<int>(n)),
capacity(n, vector<int>(n)) {}
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 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);
}
}
}
};
#include <iostream>
#include <vector>
#include <algorithm>
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;
}
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
vector<int> vertices(n);
iota(vertices.begin(), vertices.end(), 0);
sort(vertices.begin(), vertices.end(), [&](int a, int b) {
return degree[a] < degree[b];
});
#include <iostream>
#include <vector>
#include <algorithm>
result[0] = 0;
int cr;
for (cr = 0; cr < n; cr++) {
if (available[cr]) break;
}
result[u] = cr;
}
#include <iostream>
#include <vector>
#include <queue>
while (!q.empty()) {
int u = q.front();
q.pop();
#include <iostream>
#include <vector>
#include <queue>
class HopcroftKarp {
public:
HopcroftKarp(int n, int m) : n(n), m(m), pairU(n + 1, 0), pairV(m + 1, 0),
dist(n + 1) {}
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;
}
};
#include <iostream>
#include <vector>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
class Blossom {
public:
Blossom(int n) : n(n), graph(n, vector<int>(n, 0)), match(n, -1), parent(n),
base(n), q(n) {}
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;
blossom[base[match[u]]] = true;
parent[u] = child;
child = match[u];
u = parent[child];
}
}
#include <iostream>
#include <vector>
#include <queue>
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();
#include <iostream>
#include <vector>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
Certainly! Here are the C++ functions for the algorithms you requested:
#include <iostream>
#include <vector>
private:
int n, id;
vector<bool> visited;
vector<int> low, ids;
vector<vector<int>> adj;
vector<pair<int, int>> bridges;
#include <iostream>
#include <vector>
class ArticulationPointsFinder {
public:
ArticulationPointsFinder(int n) : n(n), id(0), rootChildren(0), visited(n,
false), articulationPoints(n), ids(n), low(n), adj(n) {}
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;
#include <iostream>
#include <vector>
#include <stack>
class TarjansSCC {
public:
TarjansSCC(int n) : n(n), id(0), ids(n, -1), low(n, 0), onStack(n, false),
sccCount(0), graph(n) {}
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;
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++;
}
}
};
#include <iostream>
#include <vector>
return reach;
}
#include <iostream>
#include <vector>
#include <algorithm>
return minPath;
}
Certainly! Here are the C++ implementations for the algorithms you requested:
#include <iostream>
#include <vector>
return reach;
}
#include <iostream>
#include <vector>
#include <algorithm>
return minPath;
}
### Travelling Salesman Problem (Bitmasking and Dynamic Programming)
#include <iostream>
#include <vector>
#include <algorithm>
if (dp[mask][pos] != -1) {
return dp[mask][pos];
}
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
struct Node {
int level, cost, vertex;
vector<bool> visited;
};
struct comp {
bool operator()(const Node& a, const Node& b) {
return a.cost > b.cost;
}
};
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];
}
}
return INF;
}
#include <iostream>
#include <vector>
#include <algorithm>
#include <iostream>
#include <vector>
class BridgesFinder {
public:
BridgesFinder(int n) : n(n), id(0), bridges(0), visited(n, false), low(n),
ids(n), adj(n) {}
private:
int n, id;
vector<bool> visited;
vector<int> low, ids;
vector<vector<int>> adj;
vector<pair<int, int>> bridges;
### Algorithm to Find Level of Each Node from Root Node (Breadth-First Search)
#include <iostream>
#include <vector>
#include <queue>
while (!q.empty()) {
int u = q.front();
q.pop();
return levels;
}
#include <iostream>
#include <vector>
#include <queue>
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>
#include <iostream>
#include <vector>
return diameter;
}
#include <iostream>
#include <vector>
return false;
}
bool hamiltonianPath(vector<vector<int>>& graph, int n) {
vector<int> path(n, -1);
vector<bool> visited(n, false);
return false;
}
#include <iostream>
#include <vector>
return false;
}
return false;
}
#include <iostream>
#include <vector>
// 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;
}
#include <iostream>
#include <vector>
return transpose;
}
#include <iostream>
#include <vector>
vector<int> adj[MAXN];
int parent[MAXN][20]; // Sparse table for storing ancestors up to 2^20
if (u == v) {
return u;
}
return parent[u][0];
}
#include <iostream>
#include <vector>
#include <algorithm>
return cover;
}
#include <iostream>
#include <vector>
int maxCliqueEndingAtV =
0;
for (int u : candidates) {
maxCliqueEndingAtV = max(maxCliqueEndingAtV, clique[u]);
}
clique[v] = maxCliqueEndingAtV + 1;
maxCliqueSize = max(maxCliqueSize, clique[v]);
}
return maxCliqueSize;
}
return centroid;
}
#include <iostream>
#include <vector>
struct Edge {
int u, v, weight;
};
return minMean;
}
#include <iostream>
#include <vector>
### Number of Paths with K Edges using Dynamic Programming and Divide and Conquer
#include <iostream>
#include <vector>
return dp[k][dest];
}
#include <iostream>
#include <vector>
return dp[k][dest];
}