Basic Graph Algorithms Programming Puzzles and Competitions CIS 4900 / 5920 Spring 2009
Outline Introduction/review of graphs Some basic graph problems & algorithms Start of an example question from ICPC’07 (“Tunnels”)Tunnels
Relation to Contests Many programming contest problems can be viewed as graph problems. Some graph algorithms are complicated, but a few are very simple. If you can find a way to apply one of these, you will do well.
How short & simple? int [][] path = new int[edge.length][edge.length]; for (int i =0; i < n; i++) for (int j = 0; j < n; j++) path[i][j] = edge[i][j]; for (int k = 0; k < n; k++) for (int i =0; i < n; i++) for (int j = 0; j < n; j++) if (path[i][k] != 0 && path[k,j] != 0) { x = path[i][k] + path[k][j]; if ((path[i,j] == 0) || path[i][j] > x) path[i][j] = x; }
Directed Graphs G = (V, E) V = set of vertices (a.k.a. nodes) E = set of edges (ordered pairs of nodes)
Directed Graph V = { a, b, c, d } E = { (a, b), (c, d), (a, c), (b, d), (b, c) } c b d a
Undirected Graph V = { a, b, c, d } E = { {a, b}, {c, d}, {a, c}, {b, d}, {b, c} } c b d a
Undirected Graph as Directed V = { a, b, c, d } E = { (a, b), (b,a),(c,d),(d,c),(a,c),(c,a), (b,d),(d,b),(b,c)(c,b)} c b d a Can also be viewed as symmetric directed graph, replacing each undirected edge by a pair of directed edges.
Computer Representations Edge list Hash table of edges Adjacency list Adjacency matrix
Edge List Often corresponds to the input format for contest problems Container (set) of edges may be used by algorithms that add/delete edges.
Adjacency List Can save space and time if graph is sparse with pointers & dynamic allocation: with two arrays:
Hash Table (Associative Map) good for storing information about nodes or edges, e.g., edge weight H(1,2) 1 H(0,1) 1 etc.
Adjacency/Incidence Matrix A[i][j] = 1 → (i,j) i E A[i][j] = 0 otherwise a very convenient representation for simple coding of algorithms, although it may waste time & space if the graph is sparse.
Some Basic Graph Problems Connectivity, shortest/longest path –Single source –All pairs: Floyd-Warshall AlgorithmFloyd-Warshall Algorithm dynamic programming, efficient, very simple MaxFlow (MinCut) Iterative flow-pushing algorithms
Floyd-Warshall Algorithm Assume edgeCost(i,j) returns the cost of the edge from i to j (infinity if there is none), n is the number of vertices, and edgeCost(i,i) = 0 int path[][]; // a 2-D matrix. // At each step, path[i][j] is the (cost of the) shortest path // from i to j using intermediate vertices (1..k-1). // Each path[i][j] is initialized to edgeCost (i,j) // or ∞ if there is no edge between i and j. procedure FloydWarshall () for k in 1..n for each pair (i,j) in {1,..,n}x{1,..,n} path[i][j] = min ( path[i][j], path[i][k]+path[k][j] ); * Time complexity: O (|V| 3 ).
Details Need some value to represent pairs of nodes that are not connected. If you are using floating point, there is a value ∞ for which arithmetic works correctly. But for most graph problems you may want to use integer arithmetic. Choosing a good value may simplify code When and why to use F.P. vs. integers is an interesting side discussion.
if (path[i][k] != 0 && path[k,j] != 0) { x = path[i][k] + path[k][j]; if ((path[i,j] == 0) || path[i][j] > x) path[i][j] = x; } Suppose we use path[i][j] == 0 to indicate lack of connection. Example
ij k path[i][j] path[i][k] path[k,j] paths that go though only nodes 0..k-1 How it works
Correction In class, I claimed that this algorithm could be adapted to find length of longest cycle-free path, and to count cycle-free paths. That is not true. However there is a generalization to find the maximum flow between points, and the maximum-flow path: for k in 1,..,n for each pair (i,j) in {1,..,n}x{1,..,n} maxflow[i][j] = max (maxflow[i][j] min (maxflow[i][k], maxflow[k][j]);