Graph Theory: Definitions, Representations, and Paths - Prof. Vicki H. Allan, Assignments of Computer Science

The basics of graph theory, including definitions of graphs, successors, degrees, and paths. It also discusses adjacency matrices, connected components, and dijkstra's algorithm for finding shortest paths in a weighted graph.

Typology: Assignments

Pre 2010

Uploaded on 07/30/2009

koofers-user-kui-1
koofers-user-kui-1 🇺🇸

10 documents

1 / 32

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Chapter 9
Graphs
You know about trees. They have a rigid structure of each node have a single node that points to
it (or none, in the case of the root). Sometimes life isn’t so structured.
For example: I need to fly to Tokyo. I want to find the cheapest way to fly there. How could I
think about the data?
For example: Everybody in the class has candy bars they love and some they don’t. I have a set
of candy bars in this bag. I want to distribute so everybody gets a kind they like. How do I
represent the data?
For example: I want to travel every bike path in Logan (assuming they had any ) but I don’t
want to ever travel on the same path twice. Can I begin at my home, visit every path, and then
return?
The data representation in all of these cases is the graph!
Definitions
Graph – set of vertices and set of edges.
oMore formally, a graph
),( EVG
is an ordered pair of finite sets V and E.
The set V is the set of vertices.
The set E is the set of edges.
Sometimes the edges have weight (termed a weighted graph)
Sometimes the edges have direction (I can go from A to B but not B to A).
A graph with directed edges is termed a digraph or directed graph.
Otherwise, we call in “undirected”.
Successor – the follows relationship in a directed graph.
Degree – the number of edges incident to or touching a vertex.
oIn-degree – the number of edges coming into a vertex (digraph only).
oOut-degree – the number of edges going out of a vertex (digraph only).
Predecessor – the precedes relationship in a directed graph.
Make a graph of five people around you now. The people become the nodes. Let edges be “is
born in the same year as you”. Is this directed or undirected? Is in connected? (A connected
graph is which you can get from a node to every other node following arcs.)
What if you are all born in the same year? Then you have an edge between every pair of nodes.
This is termed “complete” – as there are no missing edges.
Graphs and Paths Page 1
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20

Partial preview of the text

Download Graph Theory: Definitions, Representations, and Paths - Prof. Vicki H. Allan and more Assignments Computer Science in PDF only on Docsity!

Chapter 9

Graphs

You know about trees. They have a rigid structure of each node have a single node that points to it (or none, in the case of the root). Sometimes life isn’t so structured. For example: I need to fly to Tokyo. I want to find the cheapest way to fly there. How could I think about the data? For example: Everybody in the class has candy bars they love and some they don’t. I have a set of candy bars in this bag. I want to distribute so everybody gets a kind they like. How do I represent the data? For example: I want to travel every bike path in Logan (assuming they had any  ) but I don’t want to ever travel on the same path twice. Can I begin at my home, visit every path, and then return? The data representation in all of these cases is the graph!

Definitions

Graph – set of vertices and set of edges. o More formally, a graph G^ (^ V^ , E ) is an ordered pair of finite sets V and E.  The set V is the set of vertices.  The set E is the set of edges.  Sometimes the edges have weight (termed a weighted graph)  Sometimes the edges have direction (I can go from A to B but not B to A). A graph with directed edges is termed a digraph or directed graph. Otherwise, we call in “undirected”.  Successor – the follows relationship in a directed graph.  Degree – the number of edges incident to or touching a vertex. o In-degree – the number of edges coming into a vertex (digraph only). o Out-degree – the number of edges going out of a vertex (digraph only).  Predecessor – the precedes relationship in a directed graph. Make a graph of five people around you now. The people become the nodes. Let edges be “is born in the same year as you”. Is this directed or undirected? Is in connected? (A connected graph is which you can get from a node to every other node following arcs.) What if you are all born in the same year? Then you have an edge between every pair of nodes. This is termed “complete” – as there are no missing edges.

For the same five people, let the edges be “A likes B”. Draw the graph. Is this directed or undirected? Why? What are the characteristics of the node with the largest in-degree? (most liked?) What are the characteristics of the node with the largest out-degree? (most liking?)

How will we store a graph?

Representation of Graphs

 For the discussion below, consider the graph shown in Figure 1. Figure 1 A Direct Graph For the purposes of discussion, let’s assume this graph is the graph of people where the arcs represent “likes”. (It is a little sad as “likes” is never reciprocal, but oh well…)

Adjacency Matrix

 When two nodes are connected by an edge, we say the nodes are adjacent. So an adjacency matrix stores the edges.

 An adjacency matrix for an n -vertex graph G^ (^ V^ , E )is an n^  n^ Boolean matrix A.

A[i][j] indicating if there is an edge between i and j..  Elements of the array can be Boolean (to indicate edge existence) or can be the weight of the edge (where 9999 or -9999 represents no edge at all)  Common operations: o Determine whether there is an edge from vertex i to vertex j. (In our case, does i like j?) o Find all vertices from a given vertex i. (In our case, who does i like?)  For the graph in Figure 1, the adjacency matrix is shown in Figure 2.                       0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 1 1 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0 1 0 1 0 0 0 Figure 2 Adjacency Matrix

int ToNode; // Node id of target of edge int FromNode; // Node id of source of edge int Distance; // Cost of Edge (for a weighted graph only) EdgeNode *Next; // Next edge in linked list for adjacency list representation // Constructor – note the use of default parameters. // Note the strange assignments (Distannce(d)) – they aren’t my favorite either, but texts seem to like them EdgeNode( int F = -1, int T=-1, int d=0, EdgeNode *N = NULL): Distance(d),ToNode( T ), FromNode(F), Next( N ){}; }; // EdgeNode class GraphNode { public: inf nodeID; // ID of node; we need something that makes it easy to find the node in the array string Name; // Node name EdgeNode *Adj; // Adjacency list bool visited; // true if visited already GraphNode( int E = -1, string name=" ", EdgeNode *A = NULL): Element(E), Name(name), Adj(A){ visited = false;} }; // GraphNode class Graph { protected: GraphNode *G; // Array of nodes of graph – will be given space once the size is known int nodeCt; // Size of G public: Graph(int size ) { G = new GraphNode[size]; nodeCt = size;}; // create node array void PrintGraph(string label,ostream & fout); void BuildGraph(istream & inf); }; // Graph

How do I represent an undirected graph using this method? (an edge is

placed twice, once for A B and once for BA)

Efficiency Considerations

 There is a difference in efficiency depending on implementation. With your neighbor, decide which is the best (most efficient) representation to use if you know you will need to perform lots of the following: o Is there an edge? – (better with matrix). o Find all predecessors – (better with matrix). o Find all successors – (better with adjacency list). o Which is better for space if there are few edges (adjacency list) At your seats: Let’s do the same functions as before, but with the adjacency list representation. (d) isEdge(i,j) - returns true if there is an edge directly from i to j (e) printSucc(i) – prints the names of all nodes that are successors to i (f) countPred(i) – counts the number of predecessors of node i

More definitions: Sometimes we aren’t interested in the whole graph. Suppose the graph below represents one way streets in a town and the nodes represent hotels. Maybe I only care about hotels 0,1,3,6. I could take those nodes and the edges between them and talk about the subgraph.  Subgraph – a graph that consists of a subset of vertices and a subset of edges. Normally, the edges are all edges between the vertices and no others.  By definition a graph does not contain o Multiple copies of the same edge. o Self-edges – edges of the form (^ i ,^ i ). This is also called a loop.  If we need multiple edges between nodes, it is termed a Multigraph. In our hotel example, multiple edges between 6 and 5 could represent two different road between the hotels.

Sometimes we want to talk about a sequence of edges:

Path – a sequence of edges (one ends where next begins)  Simple path – there are no repeated vertices or edges.  Length of a path – the sum of the lengths of the edges on the path. Sometimes we want to talk about cylces (a path that begins and ends at the same place)  Simple cycle – a cycle with no repeated vertices (except at the beginning and end). The cycle (0 3  2 0) in the graph above is a simple cycle.

Figure 8 Make ChocolatesDag – directed acyclic graph. Arcs represent a partial order among vertices.  Flowgraph – dag with a unique entry node.  Total ordering – when there is an ordering between every two vertices.

 Topological ordering – an ordering such that for each edge ^ i ,^ j , i precedes j in the list.

Greedy criteria – for the unnumbered nodes, assign a number to a node for which all predecessors have been numbered. The algorithm to find a topological order is a bit tricky. Algorithm – Initially count how many predecessors each node has. The predecessor count is best thought of as the number of “unscheduled” or “unordered” predecessors it has.  For each node with predecessor count of zero, put it in a container (stack, queue, anything will do).

  1. Remove a node with predecessor count of zero from the container, order it - number it (sequentially), then print it.
  2. For each successor, decrement its predecessor count.
  3. If a successor now has a predecessor count of zero, add it to the container.  What is the Complexity – assuming an adjacency list representation for the graph.
  4. Find predecessor count. (^ e ), where e is number of edges.
  5. List node – for each successor, update predecessor count. (^ e^  n ), since if have lots of nodes with no predecessors, n could be more than e.

Shortest Paths

 Given a digraph (directed graph) with each edge in the graph having a nonnegative cost (or length).  Try to find the shortest paths (in a digraph) from a node to all other nodes. Unweighted Shortest Path We want the length of the shortest path from one node to all others. We are only interested in the number of edges – not the length of each. Could do a breadth first search. Notice, the first time we reach a node will be the quickest way to get there. Figure 9.16 in the book is a bad way to write it. We want an algorithm using a queue. void PrintShortestPath( int source) Queue q; q.enqueue(Pair(source,0)); while (!q.isEmpty()) { Pair p = dequeue(); if (!V[p->node].isVisited) {V[p->node].isVisited = true; cout << “The shortest distance from “ << source << “ to “ << p.node << “ is “ << p.dist; for (Edge * e = V[source].adj; e!= NULL; e = e->next) q.enqueue( Pair(e->toNode, p.dist+1)); }

The first time we pull a node off the queue, its best distance is known. However, if all edges are not the same length, it won’t work; we must look at edge weights. Since we have weighted edges, the only differences are  add the edgewt from node to its successor to the current distance  pull nodes off based on shortest distance – using a priority queue

We take the event graph above, and make the nodes arcs in our graph. We add dummy nodes and edges to handle nodes with more than one predecessor. Now, we are interested in the longest path. The longest path wouldn’t make since if we had cycles. We can adapt the shortest path algorithm to compute a longest path. Each nodes distance is the longest path from any predecessor. If we visit nodes in topological order, we can easily find earliest completion time. If we consider nodes in reverse topological order, we can see the latest completion times. In the figure below, the edges are labeled with name/cost/slack. A dummy terminal node is added so reverse topological order easy. The value on top of a node is the earliest time to get to the node (with all predecessors completed). The value below a node is the latest time to get to the node without affecting the critical time. Anything with a zero slack is a critical activity.

All Pairs Shortest Path (Section 10.3.4)  The basic algorithm for all points shortest path is as follows: Floyd Warshall Algorithm for k = 1 to v for i = 1 to v if path[i,k] != infinity (no path) for` j = 1 to v path[i,j] = min(path[i,j], path[i,k]+path[k,j]) For me, it is obvious that the algorithm never finds bad path lengths – as it merely replaces the current length from i to j with a path through another node (k) if it is shorter. But it isn’t as obvious that it considers every path between i and j. Can you explain why it works? The path[i,j] is initialized to the weight of the arc from i to j. path[i][i]=0. path[i][j]= if there is no edge between i and j. However, by the time the algorithm finishes, path contains the weight of the path between i and j. In fact, at intermediate points it contains the minimal weight between the points for paths possibly going through vertices 1..k.  For example, consider the digraph Figure 7 in and calculate the shortest path. Figure 7 Shortest Path Path Array (& marks infinity) 0 8 & 9 4 & 0 1 & & & 2 0 2 & & & 3 0 7 & & 1 & 0 Path Array (allow paths going through 0)

Graph Traversal

Just like we wanted to visit all the nodes of a tree, we may want to visit all the nodes of a graph by starting at a node and following incident edges. This is called a traversal. Unlike a tree traversal, a graph traversal may not visit all the nodes. (Can you think of an example?) A graph may not even be connected. o It will visit everything it can reach, but you may need to restart the traversal to visit all the nodes. Depth-first Search  It is like a preorder traversal on a tree. Figure 4 Breadth-first Search  Consider the graph is Figure 4(a). A depth-first search (starting at node A) gives the following as the order the nodes are visited: A B E H C D F G I (there are other choices as we don’t know which child to visit first. We are assuming kids are visited in alphabetic order). Notice we never hit J  How would this be implemented? (Use a recursive algorithm following down at deep as possible before returning from the recursion. Need to mark nodes visited.)  May need to restart the process if all nodes aren’t visited when you finish. At your seats: Write the code to visit every node and print its name in the order it is visited. Note that with graphs, you may find yourself going in circles if you don’t mark the nodes as “visited” in some way.

Breadth-first Search  This is like a “by level” traversal in trees.  It is similar to a “by level” tree traversal, except: o Need visited flag so you don’t get into an infinite loop. o May need to restart the process if all nodes aren’t visited when you finish.  For the graph shown in Figure 4(a), the breadth-first search is shown in Figure 4(b).  The nodes are visited in the order: A B C D E F G H I (again, it depends on which is the first child of a node)  How would we implement the breadth-first search? Visit with your neighbor and we’ll vote on your suggestions. (You use a queue, placing the starting vertex in the queue. Then take a vertex off the queue, add unvisited adjacent vertices to the queue and mark them visited. Continue until the queue is empty.)

Connected Graphs and Components

 On an undirected graph, to make sure the graph is connected we can do a regular traversal and make sure everything has been reached.  At your seats, write the code to see if an undirected graph is connected. Note, each edge will have been added twice as an edge from AB also implies there is an edge BA.  On a directed graph what do we even mean by connectivity? There are two choices:

  1. Treat edges as undirected, and consider regular connectivity. Termed weakly connected.
  2. Only consider edges in direction of arcs. Need to make sure we can get from everywhere to everywhere. This is a bit more complicated. Termed strongly connected. Show examples of connected, weakly connected, and strongly connected.

Section 9.4 Network Flow Problems

Practical examples of a network

  • liquids flowing through pipes
    • parts through assembly lines
    • current through electrical network
    • information through communication network
    • goods transported on the road… Informal definition of the max-flow problem: What is the greatest rate at which material can be shipped from the source to the sink without violating any capacity contraints? Each edge represents maximum amount that can be transported on an edge. In solving the problem, each edge shows the amount of flow on the edge and the maximum possible flow. The text shows the graphs as three graphs (capacity, flow, and residual). The residual graph shows how much more can be placed on a given edge.

At each stage we find an augmenting path – a path in the residual graph from s to t.

  • A flow f for a network N is is an assignment of an integer value f ( e ) to each edge e that satisfies the following properties: Capacity Rule: For each edge e , 0 £ f ( e ) £ c ( e ) Conservation Rule: For each vertex v ¹ s,t where E - ( v ) and E +( v ) are the incoming and outgoing edges of v , resp.
  • The value of a flow f , denoted | f |, is the total flow from the source, which is the same as the total flow into the sink
  • Example: We may be unlucky and pick an augmenting path which blocks future better paths. If we send 3 units on s-a-d-t, we are done – yet we aren’t at maximum capacity. We need to allow the algorithm to change its mind. To do so, in the residual graph we allow an edge going backwards on any path with positive flow.    ^    ( ) ( ) ( ) ( ) e E v e E v f e f e

Spanning Trees

A spanning tree is a set of all of the nodes of a graph and some of the edges such that you have a tree (every node is reached). For example, suppose we have a graph where the nodes are people in this class and the edges are “knows the phone number of”. Now suppose class is cancelled. We want to tell one person and have everybody be notified. However, we don’t want a person called multiple times. If we create a spanning tree where the arcs selected represent “will call to tell about cancellation” – we can create a way of informing everyone. You may have heard this termed a “calling tree” in everyday English. How do we create a spanning tree?  BFST (graph): breadth first spanning tree: Do a breadth first traversal, but don’t consider previously visited nodes. Visit and mark nodes as they are enqueued.  DFST (graph): depth first spanning tree: Do a depth first traversal, but don’t consider previously visited nodes.visit and mark nodes as they are visited via recursion. Sometimes we number the nodes sequentially as we visit them. Such numbers are called DFS (depth first spanning) tree numbers.  DFS numbers are useful because you are attempting to give an order to nodes in the graph so you can reason about them (e.g., finding strongly connected components)

Minimum-Cost Spanning Trees

Suppose I wanted to build a power system. Everybody needed to be connected to the power supply, but no one really cared how far away they were. Now, suppose that houses are the nodes and the edges are weighted with the cost of running electrical wires between the locations. Can you see why we need a minimum cost spanning tree?  Given a weighted graph, construct the minimum-cost spanning tree.  Use the following criterion to choose the next edge to add: o From the remaining edges, select a least-cost edge whose addition to the set of selected edges forms a tree. o Very similar to Dijkstra’s shortest path algorithm. The only difference is in how you update the distance to a node. o You grow the tree starting at the source. o You place all the edges emanating from the source on the PriorityQueue. o You pull off the smallest edge in PQ which connects something that isn’t already in the tree.  Use the following algorithm (called Prim’s algorithm): Let T be the set of selected edges. Initialize T  Let TV be the set of vertices already in the tree. Set TV {^1 } n = source place all edges from n on PQ (a priority queue) while ( !PQ.isempty()) { Edge (u,v) =PQ.dequeue(); if (v is already in tree) break; Add edge (u,v) to T Mark v as being part the tree. place all edges from v (to nodes not in tree) on PQ } if ( |T| == n -1 ) T is a minimum-cost spanning tree else There is no minimum-cost spanning tree  See example in Figure 6 Figure 6 Prim's Algorithm