Final Review Questions - Set 2 Solutions


The following problems are final review questions from the second half of the course. They are by no means an exhaustive list.
  1. Figure 1 represents a directed graph in an adjacency list format. The adjacency lists actually list the vertices in the successor vertex sets, Succ(x) for each vertex x in the graph G. For example, the successors of vertex 1 are those is the set Succ(1) = {2,3}, meaning there are directed edges from vertex 1 to vertices 2 and 3. Describe how to compute lists of the predecessor vertices, Pred(x) for each x in the graph G, starting with an adjacency matrix, T[i,j] for G.

    Figure 1
    Vertex Number Adjacency List
    1 2, 3
    2 3, 4, 5
    3 4
    4  
    5 1

    To compute the list of predecessors, Pred(x), for a vertex x starting with an adjacency matrix T for a graph G, you can scan column x of T and make a list of the vertices y for which T[y,x] = true. For example, letting L be an initially empty list, you could use the following program strategy:

    // initialize L to be the empty list 
     
    for (y = 0; y < MaxVertexNumber; ++y) { 
      if (T[y][x] == true) { 
         L.insert(y);   // insert new member y on list L 
      } 
    }
    

     

  2. Draw the Huffman coding tree for the character frequencies in Figure 2.

    Figure 2
    Character A B C D E F G
    Frequency 7 3 8 10 1 2 6

    Recall that Huffman's algorithm is defined as follows: We maintain a forest of trees. The weight of a tree is equal to the sum of the frequencies of its leaves. We assume C is the number of characters in the tree. So, C-1 times, select the two trees, T1 and T2, of smallest weight, breaking ties arbitrarily, and form a new tree with subtrees T1 and T2. At the beginning of the algorithm, there are C single-node trees--one for each character. At the end of the algorithm there is one tree, and this is the optimal Huffman coding tree.

    Here is a trace through the building of the optimal Huffman coding tree (the frequencies of the trees appear above them):

    7    3    8    10    1    2    6
    -    -    -    --    -    -    -
    
    A    B    C    D     E    F    G
    
    
    --------------------------------
    
    
    7    3    8    10    6     3 
    -    -    -    --    -     - 
    
    A    B    C    D     G     T1 
                              /  \
    		         E    F
    
    --------------------------------
    
    
    7    8    10    6       6
    -    -    --    -       -
    
    A    C    D     G       T2
                           /  \
    		     T1    B
    		    /  \
    		   E    F
    
    
    --------------------------------
    
    
    7    8    10         12
    -    -    --         --
    A    C    D          T3
                        /  \
                      T2    G
                     /  \
    	       T1    B
                  /  \
                 E    F
    
    
    --------------------------------
           
    
    10      15              12
    --      --              --
    D       T4              T3
           /  \            /  \
          A    C         T2    G
                        /  \
    	          T1    B
                     /  \
                    E    F
    
    
    --------------------------------
    
    
      15                22
      --                --
      T4                T5
     /  \              /  \
    A    C           T3    D 
                    /  \
                  T2    G
                 /  \
               T1    B
              /  \
             E    F
    
    
    --------------------------------
    
    The optimal Huffman coding tree:
    
                   37
    	       --
           	       T6
                 /    \
               T5      T4
              /  \    /  \
            T3    D  A    C
           /  \
         T2    G
        /  \
      T1    B
     /  \
    E    F
    

     

  3. Figure 3 is a table of mileage distances between 7 cities. Suppose you want to build a pipeline that links all these cities using the minimum amount of pipe. List the city-pairs that would be linked in building this pipeline.

    Figure 3
    City Denver Salt Lake Albuquerque Oklahoma City Cheyenne Omaha
    Salt Lake 512          
    Albuquerque 422 611        
    Oklahoma City 615 1108 525      
    Cheyenne 102 462 522 706    
    Omaha 540 955 895 454 493  
    Dodge City 301 682 425 212 355 336

    The trick is to use Kruskal's Algorithm. Recall that Kruskal`s algorithm is a greedy strategy that continually selects the edges in order of smallest weight and accepts an edge if it does not cause a cycle. Formally, Kruskal's algorithm maintains a forest--a collection of trees. Initially, there are |V| single-node trees. Adding an edge merges two trees into one. When the algorithm terminates, there is only one tree, and this is the minimum spanning tree.

    Here is the pseudocode for Kruskal's algorithm given in the Weiss book:

    public void kruskal() 
    {
      int edgesAccepted;
      DisjSet s;
      PriorityQueue h;
      Vertex u, v;
      SetType uset, vset;
      Edge e;
    
      h = readGraphIntoHeapArray();
      h.buildHeap();
      s = new DisjSet( NUM_VERTICES );
      
      edgesAccepted = 0;
      while( edgesAccepted < NUM_VERTICES - 1 ) 
      {
        e = h.deleteMin();   // Edge e = (u,v)
        uset = s.find( u );
        vset = s.find( v );
        if ( uset != vset )
        {
          // Accept the edge
          edgesAccepted++;
          s.union( uset, vset );
        }
      }
    }
    

    You can think of Figure 3 as containing the adjacency matrix information for a weighted graph of cities. The pairs of cities (edges) accepted are:

    1. (Cheyenne, Denver) weight = 102
    2. (Dodge City, Oklahoma City) weight = 212
    3. (Dodge City, Denver) weight = 301
    4. (Dodge City, Omaha) weight = 336
    5. (Albuquerque, Denver) weight 422
    6. (Cheyenne, Salt Lake) weight = 462

    Here is what the graph might look like (by the way, this graph is not geographically correct nor is it drawn to scale):

                102                  422
    Cheyenne--------------Denver--------------Albuquerque
       |		       |
       |		       |
       | 462	       | 301
       |		       |
       |		       |         212
    Salt Lake	  Dodge City-------------Oklahoma City
    		       |
    		       |
    		       | 336
    		       |
    		       |
    		     Omaha
    

     

    1. Explain how to modify Dijkstra's algorithm to produce a count of the number of different minimum paths from v to w.

      Use an array count such that for any vertex u, count[u] is the number of distinct paths from s to u known so far. When a vertex v is marked as known, its adjacency list is traversed. Let w be a vertex on the adjacency list.
      If dv + cv,w = dw, then increment count[w] by count[v] because all shortest paths from s to v with last edge (v,w) give a shortest path to w.
      If dv + cv,w < dw, then pw and dw get updated. All previously known shortest paths to w are now invalid, but all shortest paths to v now lead to shortest paths for w, so set count[w] to equal count[v]. Note: Zero-cost edges mess up this algorithm.

    2. Explain how to modify Dijkstra's algorithm so that if there is more than one minimum path from v to w, a path with the fewest number of edges is chosen.

      Use an array numEdges such that for any vertex u, numEdges[u] is the shortest number of edges on a path of distance du from s to u known so far. Thus numEdges is used as a tiebreaker when selecting the vertex to mark. As before, v is the vertex marked known, and w is adjacent to v.
      If dv + cv,w = dw, then change pw to v and numEdges[w] to numEdges[v] + 1 if numEdges[v] + 1 < numEdges[w].
      If dv + cv,w < dw, then update pw and dw, and set numEdges[w] to numEdges[v] + 1.


[CS3139 Home]