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

Post on 22-Aug-2020

7 views 0 download

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

   

<Graph Theory 10>

December 11111011010

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

­­ Benjamin Burton, (year unknown)

   

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

   

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

   

Lowest Common Ancestor

   

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.

   

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

   

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];

   

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;

   

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.

   

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

   

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]

   

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.

   

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.

   

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;

}}

   

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]);

}}

   

State explosion

+

   

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.

   

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.

   

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.

   

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.

   

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.

   

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

   

</Graph Theory 10>

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