public int[] dijkstra(Node source) {

    dist = new int[nodes.length];
    previous = new Node[nodes.length];
    Arrays.fill(dist, Integer.MAX_VALUE);

    dist[source.id] = 0;

    Queue<Node> queue = new PriorityQueue<Node>();
    for (int i = 0; i < nodes.length; i++) {
      queue.add(nodes[i]);
    }

    while (!queue.isEmpty()) {

      Node u = queue.poll();
      if (dist[u.id] == Integer.MAX_VALUE) break;

      for (int i = 0; i < nodes.length; i++) {
        if (!u.equals(nodes[i]) && weights[u.id][i] > 0) {

          int distance = dist[u.id] + weights[u.id][i];
          if (distance < dist[nodes[i].id]) {
            dist[nodes[i].id] = distance;
            previous[nodes[i].id] = u;
          }
        }
      }
    }

    return dist;
  }
  public int countPaths(Node source, Node destination) {
    if (source.equals(destination)) return 1;

    int count = 0;

    for (int i = 0; i < nodes.length; i++) {
      if (!source.equals(nodes[i]) && weights[source.id][i] > 0) {
        count = count + countPaths(nodes[i], destination);
      }
    }

    return count;
  }
  public boolean pathExists(Node source, Node destination) {

    if (source.equals(destination)) return true;

    boolean pathExists = false;
    for (int i = 0; i < nodes.length; i++) {
      if (!source.equals(nodes[i]) && weights[source.id][i] > 0) {
        pathExists = pathExists || pathExists(nodes[i], destination);
        if (pathExists) break;
      }
    }

    return pathExists;
  }