public Set<Edge> getMST() {
      // uses Kruskal's algorithm
      DisjointSets disjEdges = new MyDisjSets(graph.keySet().size());
		// vertexTable maps each vertex to an element in disjoint sets
      Map<Vertex, Integer> vertexTable = new HashMap<Vertex, Integer>();
      Set<Edge> mst = new HashSet<Edge>();
      PriorityQueue<Edge> pq = new PriorityQueue<Edge>();
      // fill priority queue with edges
      for (Vertex v : graph.keySet())
         for (Edge e : graph.get(v))
            pq.add(e);
      /* establishes a correspondence between the 0 to V-1 numbers in disj sets
      		and our vertices */
      int i = 0;
      for (Vertex v : graph.keySet()) {
         vertexTable.put(v, i);
         i++;
      }
		try {
      	// while at one or more vertices are not part of the mst
	      while (disjEdges.numSets() > 1) {
	         Edge edge = pq.remove(); // get edge of lowest cost.
				int sourceDisjElement = vertexTable.get(edge.getSource());
				int destDisjElement = vertexTable.get(edge.getDestination());
	         if (disjEdges.find(sourceDisjElement) != disjEdges.find(destDisjElement)) {
					// if there's no path from source group to destination group
					mst.add(edge);
					// union to reflect that an edge from source to dest now exists 
		         disjEdges.union(disjEdges.find(sourceDisjElement),
							disjEdges.find(destDisjElement));
	   		}   
			} 
			return mst;
		} catch (NoSuchElementException mstDNE) { // pq is empty but vertices not connected
			return null;
		}
	}