#include <bits/stdc++.h>
using namespace std;
struct UnionFind {
  vector<int> data;
  UnionFind(int sz) { data.assign(sz, -1); }
  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y) return (false);
    data[x] += data[y];
    data[y] = x;
    return (true);
  }
  int find(int k) {
    if (data[k] < 0) return (k);
    return (data[k] = find(data[k]));
  }
  int size(int k) { return (-data[find(k)]); }
};
template <typename T, typename E>
struct PairingHeap {
  using G = function<T(T, E)>;
  using H = function<E(E, E)>;
  struct Node {
    T key;
    E lazy;
    Node *head, *next;
  };
  bool rev;
  const G g;
  const H h;
  PairingHeap(bool rev = false)
      : g([](const T &a, const E &b) { return a + b; }),
        h([](const E &a, const E &b) { return a + b; }),
        rev(rev) {}
  PairingHeap(const G &g, const H &h, bool rev = false)
      : g(g), h(h), rev(rev) {}
  Node *propagate(Node *t) {
    if (t->lazy != 0) {
      if (t->next) t->next->lazy = h(t->next->lazy, t->lazy);
      t->key = g(t->key, t->lazy);
      t->lazy = 0;
    }
    return t;
  }
  Node *merge(Node *x, Node *y) {
    if (!x || !y) return x ? x : y;
    propagate(x);
    propagate(y);
    if ((x->key > y->key) ^ rev) swap(x, y);
    y->next = x->head;
    x->head = y;
    return x;
  }
  void push(Node *&root, const T &key) {
    root = merge(root, new Node({key, 0, nullptr, nullptr}));
  }
  T top(Node *root) { return propagate(root)->key; }
  Node *_pop(Node *s) {
    Node *p = nullptr;
    while (s) {
      Node *a = s, *b = nullptr;
      propagate(s);
      s = s->next;
      a->next = nullptr;
      if (s) {
        propagate(s);
        b = s;
        s = s->next;
        b->next = nullptr;
      }
      a = merge(a, b);
      a->next = p;
      p = a;
    }
    while (p) {
      Node *j = p;
      propagate(p);
      p = p->next;
      s = merge(j, s);
    }
    return s;
  }
  void pop(Node *&root) {
    auto *temp = root;
    root = _pop(root->head);
  }
  bool empty(Node *root) const { return !root; }
  void add(Node *root, const E &lazy) {
    if (root) {
      root->lazy = h(root->lazy, lazy);
      propagate(root);
    }
  }
  Node *makeheap() { return nullptr; }
};
template <typename T>
struct edge {
  int src, to;
  T cost;
  edge(int to, T cost) : src(-1), to(to), cost(cost) {}
  edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}
  operator int() const { return to; }
};
template <typename T>
using Edges = vector<edge<T> >;
template <typename T>
using WeightedGraph = vector<Edges<T> >;
using UnWeightedGraph = vector<vector<int> >;
template <typename T>
using Matrix = vector<vector<T> >;
template <typename T>
struct MinimumSpanningTreeArborescence {
  using Pi = pair<T, int>;
  using Heap = PairingHeap<Pi, int>;
  using Node = typename Heap::Node;
  const Edges<T> &es;
  const int V;
  T INF;
  MinimumSpanningTreeArborescence(const Edges<T> &es, int V)
      : INF(numeric_limits<T>::max()), es(es), V(V) {}
  T build(int start) {
    auto g = [](const Pi &a, const T &b) { return Pi(a.first + b, a.second); };
    auto h = [](const T &a, const T &b) { return a + b; };
    Heap heap(g, h);
    vector<Node *> heaps(V, heap.makeheap());
    for (auto &e : es) heap.push(heaps[e.to], {e.cost, e.src});
    UnionFind uf(V);
    vector<int> used(V, -1);
    used[start] = start;
    T ret = 0;
    for (int s = 0; s < V; s++) {
      stack<int> path;
      for (int u = s; used[u] < 0;) {
        path.push(u);
        used[u] = s;
        if (heap.empty(heaps[u])) return -1;
        auto p = heap.top(heaps[u]);
        ret += p.first;
        heap.add(heaps[u], -p.first);
        heap.pop(heaps[u]);
        int v = uf.find(p.second);
        if (used[v] == s) {
          int w;
          Node *nextheap = heap.makeheap();
          do {
            w = path.top();
            path.pop();
            nextheap = heap.merge(nextheap, heaps[w]);
          } while (uf.unite(v, w));
          heaps[uf.find(v)] = nextheap;
          used[uf.find(v)] = -1;
        }
        u = uf.find(v);
      }
    }
    return ret;
  }
};
void solve() {
  int V, E, R;
  cin >> V >> E >> R;
  Edges<int> g;
  while (E--) {
    int a, b, c;
    cin >> a >> b >> c;
    g.emplace_back(a, b, c);
  }
  MinimumSpanningTreeArborescence<int> v(g, V);
  cout << v.build(R) << endl;
}
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  solve();
}
