orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith...

23
 <Graph Theory 10> December 11111011010 "Everything is a graph, and a graph is everything." -- Benjamin Burton, (year unknown)

Transcript of orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith...

Page 1: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

<Graph Theory 10>

December 11111011010

"Everything is a graph, and a graph is everything."

­­ Benjamin Burton, (year unknown)

Page 2: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Trees

● Connected and has N nodes, N­1 edges

● Connected and has no cycles

● If any edge is added, exactly one cycle is formed

● If any edge is removed, the graph is disconnected

● There exists one unique path between any two nodes

● Trees can be rooted or unrooted.

● Nodes have one parent and zero or more children.

● Leaves have zero children.

● Every node is a subtree

Page 3: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Funky tree problems

● Height (max­depth) of a tree:– depth[node] = depth[parent]+1

– height(node) = if no children: 0else: max(height(child) for each child )+1

● Breadth of a tree– Count how many nodes at each depth, output the highest count.

● Diameter of a tree– diameter(node) = depth[deepest child] 

  + depth[2nd deepest child]

– Pick node with largest diameter.

● Length of path between two nodes

Page 4: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Lowest Common Ancestor

Page 5: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Lowest Common Ancestor

● Store the parent of each node● Store the height of each node:

– height[node] = height[parent[node]] + 1

● We could store the grandparent of each node– gparent[node] = parent[parent[node]]

● And store their great­great­grandparents...– gggparent[node] = gparent[gparent[node]]

● etc.

Page 6: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Lowest Common Ancestor

● parent[node][i] : the 2ith ancestor of 'node'● parent[node][0] : its normal parent (20 = 1)● parent[node][1] : its grandparent (21 = 2)● parent[node][2] : its gg­grandparent (22 = 4)● parent[node][3] : 23 = 8 nodes up the tree● This is really cool because:

– parent[node][i] = parent[parent[node][i­1]][i­1]

● With 'k' sweeps of the whole tree, we can easily precompute the parent[][] table

Page 7: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Lowest Common Ancestor

● If parent[ node ] [ k ] = 0, then it doesn't have a 2k th parent (ie. its level is < 2k)

● In logarithmic time, we can now calculate the node 'm' steps up the tree for any node.

set parent[i][j] to 0 for all i,jinput parent[i][0] for all i

for (i = 1; i <= MAX_K; i++) for (j = 1; j <= n; j++) 

parent[j][i] = parent[ parent[j][i­1] ][i­1];

Page 8: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Lowest Common Ancestor

● Wait a minute Jarrah, what has this got to do with lowest common ancestor?

//get the node 'm' steps up from node 'node'// MAX_K is defined to be log

2(maximum nodes in tree)

for (k = MAX_K; k >= 0; k­­) {if (pow2(k) <= m) {

node = parent[node][k];m ­= pow2(k);

}}return node;

Page 9: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Lowest Common Ancestor

● Two nodes 'a' and 'b'. lca(a, b) = ??– 1) Get depth of a and b : O(1) after pre­comp.– 2) If depth[a] > depth[b]

  a = parent(a, depth[b]­depth[a])Likewise for b.

– 3) Now they're at the same level, yay! Their LCA must be the same distance from each. Using our epic expo­parential array, we effectively binary search for the LCA.

Page 10: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Lowest Common Ancestor

// get the lca of 'a' and 'b'// MAX_K is defined to be log

2(maximum nodes in tree)

for (k = MAX_K; k >= 0; k­­) {if (parent[a][k] != parent[b][k]) {

a = parent[a][k];b = parent[b][k];

}}assert(a == b);return a;

● In logarithmic time, you have found the lowest common ancestor.

● Yay! But how does this help us again?YOU JUST LOST THE GAME

Page 11: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Length of path in a tree

● 1) Root the tree

● 2) Pre­compute epic parents

● 3) The length of the path from a to b isdepth[a] – depth[lca(a,b)]

+  depth[b] – depth[lca(a, b)]

● If the edges were weighted, then instead of using 'depth' in the final formula, we would use 'distance', where distance[a] is the distance from 'a' to the root node. This is pre­computable in linear time – distance[node] = weight(node, parent) + distance[parent]

Page 12: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Spanning trees

● Facebook has changed their privacy settings so that you can view all default public information (name, phone, address, photos, real­time footage from cameras near your current location, etc.) for any friend­of­a­friend­of­a­friend­.......­of­a­friend. Find a (maximal) set of friendships that can be broken while still allowing everyone to view information on everyone else.

Page 13: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Spanning trees

● Any DFS will do – each node is processed only once, so if we store the edge used to reach it, we have a 'parent' for every node. We need n­1 edges to remain intact for the n nodes to stay connected.

● But what if the edges are weighted? The NBN network wants to connect every house in Australia using minimum total wiring.

Page 14: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Minimal spanning trees

● Prim's Algorithm

for (i = 0; i < n; i++) {

next = ­1;

for (j = 0; j < n; j++)if (!intree[j] && (next < 0 || dist[j] < dist[next])) 

next = j;

intree[next] = true;

for (j = 0; j < n; j++)if (!intree[j] && weight(next, j) < dist[j]) {

dist[j] = weight(next, j);parent[j] = next;

}}

Page 15: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Minimal Spanning Trees

● Kruskal's Algorithm

sort edges by weight ascending

for (i = 0; i < num_edges; i++) {

if (!path_exists(edge[i].u, edge[i].v)) {add_to_tree(edge[i]);

}}

Page 16: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

State explosion

+

Page 17: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Graphs are everywhere

● In data structures, you have lots of trees.● In DP, you have nodes (states or subproblems) 

with edges (recurrence relations). These graphs are directed and acyclic. (DAGs)

● Sometimes, even when a graph is staring at you in a problem, it may be the case that these are not the nodes you're looking for.

Page 18: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Colour Circles

● You are given a graph with nodes and edges, each node labelled a colour, and each edge labelled a colour. You have two counters, and the two nodes that they start on. You can move a counter along an edge only if the other counter is on a node of the same colour as the edge. Your goal is to get either counter into a 'target' node in the smallest number of moves.

Page 19: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Colour Circles

● 'Smallest number of moves'? That sounds like a......... shortest path problem! But then who was graph?

● By exploding the nodes of the graph to accommodate for the extra information we need (what node the other counter is on), we can create new edges between these nodes and transform the graph into one that a simple BFS will work on.

Page 20: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Colour Circles

● Vertex = pair of numbers:(node of counter A, node of counter B)

● We can travel from vertex U (p,q) to V (x,y) if:­ p = x and colour(q­>y) = colour(p), or­ q = y and colour(p­>x) = colour(q)

● Each vertex in this transformed graph corresponds to a state, each edge to a move.

● The line is blurry between 'state explosion' and 'creating an abstract graph from thin air', but the idea is what's important.

Page 21: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

What idea?

● We know we have to explode our states when  we need a bunch of information to decide our moves, rather than just a simple location.– e.g. what weapons I have in a dungeon might 

determine what monsters I can kill, hence which rooms I can enter.

● So to fix this, instead of BFSing 'dist[node]', we BFS on 'dist[node][other information]' and the combined state (node+information) is the new node in our transformed graph.

Page 22: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

Other cool tricks

● Oh noes, out of time? Ask me later about...– Multi­sourcing shortest path, e.g. given the 

locations of all the tutors + students in a graph, find the distance from every student to their closest tutor, in normal Dijkstra time complexity.

– Topsort, to find an ordering of a DAG so that every node appears before all its children.

– Hare and Tortoise: if every state has one outgoing edge, find when you hit a cycle (e.g. Relocation)

– Eulerian Paths – find a path going through every single edge once and only once

Page 23: orac.amt.edu.au/notes/GraphTheory2-Dec2010.pdf · Lowest Common Ancestor parent[node][i] : the 2ith ancestor of 'node' parent[node][0] : its normal parent (20

   

</Graph Theory 10>

"Except some things aren't graphs."­­ Benjamin Burton, (year known)