private Set<Vertex> computeMinVertexCover(Set<Vertex> side1, Set<Vertex> side2) {
    Set<Vertex> konigSet = new HashSet<Vertex>();
    Set<Vertex> unmatched = new TreeSet<Vertex>(side1);
    unmatched.removeAll(matches);
    // System.out.println("Matches: " + matches);
    // System.out.println("side 1 unmatched set: " + unmatched);

    for (Vertex v : unmatched) {
      konigDFS(konigSet, v, false);
    }

    // System.out.println("Konig set: " + konigSet);

    Set<Vertex> result = new HashSet<Vertex>(side2);
    result.retainAll(konigSet);
    // System.out.println("side 2 intersect konigSet: " + result);

    Set<Vertex> side1notInKonigSet = new HashSet<Vertex>(side1);
    side1notInKonigSet.removeAll(konigSet);
    // System.out.println("side 1 not in Konig set: " + side1notInKonigSet);

    result.addAll(side1notInKonigSet);

    return result;
  }
  private void konigDFS(Set<Vertex> konigSet, Vertex v, boolean edgesInMatch) {
    if (!konigSet.contains(v)) {
      konigSet.add(v);

      for (Vertex neighb : v.getNeighbors()) {
        if (neighb.getId() != SOURCE_ID && neighb.getId() != SINK_ID) {
          if (edgesInMatch == (getFlow(v, neighb) > 0 || getFlow(neighb, v) > 0)) {
            konigDFS(konigSet, neighb, !edgesInMatch);
          }
        }
      }
    }
  }