Graphs Quick Reference
Everything you need day‑to‑day – traversals, shortest paths, and algorithms.
Graph Basics
Terminology
- Vertex (V) – node
- Edge (E) – connection
- Directed – one‑way edge
- Undirected – two‑way edge
- Weighted – edge has cost
- Cycle – path starts/ends at same vertex
- Connected – path exists between any two vertices
- DAG – Directed Acyclic Graph
- Degree – number of edges (in/out for directed)
Graph Types
- Undirected Graph
- Directed Graph (Digraph)
- Weighted Graph
- Unweighted Graph
- Cyclic / Acyclic
- Connected / Disconnected
- Complete Graph
- Bipartite Graph
Graph Representations
Adjacency List
List<List<Integer>> adj = new ArrayList<>();
for (int i = 0; i < n; i++) {
adj.add(new ArrayList<>());
}
adj.get(u).add(v); // directed
adj.get(v).add(u); // undirected (add both)
// Weighted
List<List<int[]>> adj = new ArrayList<>();
adj.get(u).add(new int[]{v, w});
Adjacency Matrix
int[][] adj = new int[n][n]; adj[u][v] = 1; // directed adj[u][v] = adj[v][u] = 1; // undirected // Weighted adj[u][v] = weight; adj[v][u] = weight; // undirected
DFS (Depth‑First Search)
Recursive DFS
boolean[] visited = new boolean[n];
void dfs(int u, List<List<Integer>> adj) {
visited[u] = true;
System.out.print(u + " ");
for (int v : adj.get(u)) {
if (!visited[v]) {
dfs(v, adj);
}
}
}
// DFS with parent (for cycle detection)
boolean hasCycle(int u, int parent, List<List<Integer>> adj, boolean[] visited) {
visited[u] = true;
for (int v : adj.get(u)) {
if (!visited[v]) {
if (hasCycle(v, u, adj, visited)) return true;
} else if (v != parent) {
return true;
}
}
return false;
}
Iterative DFS (Stack)
void dfsIterative(int start, List<List<Integer>> adj) {
boolean[] visited = new boolean[n];
Stack<Integer> stack = new Stack<>();
stack.push(start);
while (!stack.isEmpty()) {
int u = stack.pop();
if (!visited[u]) {
visited[u] = true;
System.out.print(u + " ");
for (int v : adj.get(u)) {
if (!visited[v]) stack.push(v);
}
}
}
}
BFS (Breadth‑First Search)
void bfs(int start, List<List<Integer>> adj) {
boolean[] visited = new boolean[n];
Queue<Integer> q = new LinkedList<>();
visited[start] = true;
q.offer(start);
while (!q.isEmpty()) {
int u = q.poll();
System.out.print(u + " ");
for (int v : adj.get(u)) {
if (!visited[v]) {
visited[v] = true;
q.offer(v);
}
}
}
}
// BFS with distance (shortest path in unweighted graph)
int[] bfsDistance(int start, List<List<Integer>> adj) {
int[] dist = new int[n];
Arrays.fill(dist, -1);
Queue<Integer> q = new LinkedList<>();
dist[start] = 0;
q.offer(start);
while (!q.isEmpty()) {
int u = q.poll();
for (int v : adj.get(u)) {
if (dist[v] == -1) {
dist[v] = dist[u] + 1;
q.offer(v);
}
}
}
return dist;
}
Shortest Path Algorithms
Dijkstra (Single Source – Non‑negative Weights)
int[] dijkstra(int src, List<List<int[]>> adj, int n) {
int[] dist = new int[n];
Arrays.fill(dist, Integer.MAX_VALUE);
dist[src] = 0;
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[1] - b[1]);
pq.offer(new int[]{src, 0});
while (!pq.isEmpty()) {
int[] curr = pq.poll();
int u = curr[0];
int d = curr[1];
if (d > dist[u]) continue;
for (int[] edge : adj.get(u)) {
int v = edge[0];
int w = edge[1];
if (dist[u] + w < dist[v]) {
dist[v] = dist[u] + w;
pq.offer(new int[]{v, dist[v]});
}
}
}
return dist;
}
Bellman‑Ford (Negative Weights, Detects Negative Cycles)
int[] bellmanFord(int src, int[][] edges, int n) {
int[] dist = new int[n];
Arrays.fill(dist, Integer.MAX_VALUE);
dist[src] = 0;
for (int i = 0; i < n - 1; i++) {
for (int[] edge : edges) {
int u = edge[0], v = edge[1], w = edge[2];
if (dist[u] != Integer.MAX_VALUE && dist[u] + w < dist[v]) {
dist[v] = dist[u] + w;
}
}
}
// Check for negative cycles
for (int[] edge : edges) {
int u = edge[0], v = edge[1], w = edge[2];
if (dist[u] != Integer.MAX_VALUE && dist[u] + w < dist[v]) {
return null; // negative cycle detected
}
}
return dist;
}
Floyd‑Warshall (All‑Pairs Shortest Path)
void floydWarshall(int[][] dist, int n) {
for (int k = 0; k < n; k++) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (dist[i][k] != INF && dist[k][j] != INF) {
dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]);
}
}
}
}
}
Minimum Spanning Tree (MST)
Prim's Algorithm
int prim(List<List<int[]>> adj, int n) {
boolean[] visited = new boolean[n];
int[] minEdge = new int[n];
Arrays.fill(minEdge, Integer.MAX_VALUE);
minEdge[0] = 0;
int total = 0;
for (int i = 0; i < n; i++) {
int u = -1;
for (int j = 0; j < n; j++) {
if (!visited[j] && (u == -1 || minEdge[j] < minEdge[u])) {
u = j;
}
}
visited[u] = true;
total += minEdge[u];
for (int[] edge : adj.get(u)) {
int v = edge[0], w = edge[1];
if (!visited[v] && w < minEdge[v]) {
minEdge[v] = w;
}
}
}
return total;
}
Kruskal's Algorithm (Union‑Find)
class UnionFind {
int[] parent, rank;
UnionFind(int n) {
parent = new int[n];
rank = new int[n];
for (int i = 0; i < n; i++) parent[i] = i;
}
int find(int x) {
if (parent[x] != x) parent[x] = find(parent[x]);
return parent[x];
}
boolean union(int a, int b) {
int ra = find(a), rb = find(b);
if (ra == rb) return false;
if (rank[ra] < rank[rb]) { int temp = ra; ra = rb; rb = temp; }
parent[rb] = ra;
if (rank[ra] == rank[rb]) rank[ra]++;
return true;
}
}
int kruskal(int[][] edges, int n) {
Arrays.sort(edges, (a, b) -> a[2] - b[2]); // sort by weight
UnionFind uf = new UnionFind(n);
int total = 0, count = 0;
for (int[] edge : edges) {
int u = edge[0], v = edge[1], w = edge[2];
if (uf.union(u, v)) {
total += w;
count++;
if (count == n - 1) break;
}
}
return total;
}
Topological Sort (DAG)
DFS Method
void topologicalSortDFS(List<List<Integer>> adj, int n) {
boolean[] visited = new boolean[n];
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < n; i++) {
if (!visited[i]) dfsTopo(i, adj, visited, stack);
}
while (!stack.isEmpty()) System.out.print(stack.pop() + " ");
}
void dfsTopo(int u, List<List<Integer>> adj, boolean[] visited, Stack<Integer> stack) {
visited[u] = true;
for (int v : adj.get(u)) {
if (!visited[v]) dfsTopo(v, adj, visited, stack);
}
stack.push(u);
}
Kahn's Algorithm (BFS / Indegree)
int[] topologicalSortKahn(List<List<Integer>> adj, int n) {
int[] indegree = new int[n];
for (int u = 0; u < n; u++) {
for (int v : adj.get(u)) indegree[v]++;
}
Queue<Integer> q = new LinkedList<>();
for (int i = 0; i < n; i++) {
if (indegree[i] == 0) q.offer(i);
}
int[] result = new int[n];
int idx = 0;
while (!q.isEmpty()) {
int u = q.poll();
result[idx++] = u;
for (int v : adj.get(u)) {
if (--indegree[v] == 0) q.offer(v);
}
}
return (idx == n) ? result : null; // null if cycle
}
Common Graph Problems
Easy
- Number of Connected Components
- BFS / DFS Traversal
- Find Path (DFS/BFS)
- Detect Cycle (Undirected)
- Bipartite Graph Check
Medium
- Shortest Path (BFS)
- Dijkstra (Weighted)
- Topological Sort
- Detect Cycle (Directed)
- Course Schedule
- Number of Islands
Hard
- Dijkstra with State
- Bellman‑Ford / Floyd‑Warshall
- Kruskal / Prim (MST)
- Alien Dictionary
- Critical Connections
- Word Ladder
Complexities Summary
| Algorithm | Time Complexity | Space Complexity |
|---|---|---|
| DFS / BFS | O(V + E) | O(V) |
| Dijkstra (Heap) | O((V + E) log V) | O(V) |
| Dijkstra (Array) | O(V²) | O(V) |
| Bellman‑Ford | O(VE) | O(V) |
| Floyd‑Warshall | O(V³) | O(V²) |
| Prim (Adj Matrix) | O(V²) | O(V) |
| Prim (Heap) | O(E log V) | O(V) |
| Kruskal | O(E log E) | O(V) |
| Topological Sort | O(V + E) | O(V) |
📌 Quick Reference
Unweighted shortest path: BFS
Weighted no negative: Dijkstra (Heap)
Negative weights: Bellman‑Ford
All‑pairs: Floyd‑Warshall
MST: Prim (dense) or Kruskal (sparse)
Cycle detection (undirected): DFS with parent
Cycle detection (directed): DFS with 3 states or Kahn's
DAG ordering: Topological Sort (DFS or Kahn's)
Weighted no negative: Dijkstra (Heap)
Negative weights: Bellman‑Ford
All‑pairs: Floyd‑Warshall
MST: Prim (dense) or Kruskal (sparse)
Cycle detection (undirected): DFS with parent
Cycle detection (directed): DFS with 3 states or Kahn's
DAG ordering: Topological Sort (DFS or Kahn's)