Graphs and how to store them
Learn what a graph is (vertices, edges, directed, weighted, cycles), where graphs appear in real software, and how to store one as an adjacency list, an adjacency matrix or an edge list.
The vocabulary
| Term | Meaning |
|---|---|
Adjacency list: each vertex knows its neighbours
var roads = new Dictionary<string, List<(string To, int Minutes)>>(); void AddRoad(string a, string b, int minutes){ if (!roads.ContainsKey(a)) roads[a] = new(); if (!roads.ContainsKey(b)) roads[b] = new(); roads[a].Add((b, minutes)); // undirected: store both directions roads[b].Add((a, minutes));} AddRoad("Gate", "Store", 4);AddRoad("Gate", "Office", 2);AddRoad("Store", "Yard", 3);AddRoad("Office", "Yard", 5); foreach (var (place, list) in roads) Console.WriteLine($"{place}: {string.Join(", ", list.Select(r => $"{r.To} ({r.Minutes})"))}"); Console.WriteLine($"Degree of Yard: {roads["Yard"].Count}");Gate: Store (4), Office (2) Store: Gate (4), Yard (3) Office: Gate (2), Yard (5) Yard: Store (3), Office (5) Degree of Yard: 2
string[] names if you need the labels back.
Adjacency matrix: a V × V table
m[i, j] holds 1 (or the weight) if there is an edge from i to j. Checking one particular connection is O(1), but the table always uses V² cells, even when there are few edges, and listing the neighbours of a vertex means scanning a whole row.
int n = 5;int[][] edges = { new[] { 0, 1 }, new[] { 0, 2 }, new[] { 1, 3 }, new[] { 2, 3 }, new[] { 3, 4 } }; var adj = new List<int>[n]; // adjacency listfor (int i = 0; i < n; i++) adj[i] = new List<int>();var matrix = new bool[n, n]; // adjacency matrix foreach (var e in edges){ adj[e[0]].Add(e[1]); adj[e[1]].Add(e[0]); matrix[e[0], e[1]] = matrix[e[1], e[0]] = true;} for (int i = 0; i < n; i++) Console.WriteLine($"{i}: {string.Join(" ", adj[i])}");Console.WriteLine(matrix[3, 4]); // is there an edge 3-4? O(1)Console.WriteLine(matrix[0, 4]);0: 1 2 1: 0 3 2: 0 3 3: 1 2 4 4: 3 True False
| Adjacency list | Adjacency matrix | Edge list | |
|---|---|---|---|
Graphs you never build
Show a hint
Dictionary<string, int>. For each pair, make sure the first task exists with TryAdd(task, 0), and add 1 to the second task.
Show the solution
var deps = new (string Before, string After)[]{ ("Survey", "Excavate"), ("Excavate", "Footings"), ("Order steel", "Fabricate"), ("Fabricate", "Columns"), ("Footings", "Columns")}; var inDegree = new Dictionary<string, int>();foreach (var (a, b) in deps){ inDegree.TryAdd(a, 0); inDegree[b] = inDegree.GetValueOrDefault(b) + 1;} foreach (var (task, d) in inDegree) Console.WriteLine($"{task}: {d}"); var starts = inDegree.Where(p => p.Value == 0).Select(p => p.Key);Console.WriteLine("Can start now: " + string.Join(", ", starts));Survey: 0 Excavate: 1 Footings: 1 Order steel: 0 Fabricate: 1 Columns: 2 Can start now: Survey, Order steel
Remember
A graph is vertices plus edges; edges can be directed and/or weighted. Adjacency lists use O(V + E) memory and list neighbours fast: the default choice. An adjacency matrix answers “is there an edge?” in O(1) but costs O(V²) memory. Grids and puzzles are implicit graphs: compute neighbours on the fly.