#include <bits/stdc++.h>
using namespace std;
struct Edge {
  int from, to, cost;
  Edge *prevEdge;
  Edge(int from, int to, int cost, Edge *prevEdge = NULL)
      : from(from), to(to), cost(cost), prevEdge(prevEdge) {}
};
struct UnionFindTree {
  vector<int> par, sz;
  UnionFindTree(int n) {
    par.resize(n);
    sz.resize(n);
    for (int i = 0; i < n; i++) {
      par[i] = i;
      sz[i] = 1;
    }
  }
  int find(int x) { return x == par[x] ? x : par[x] = find(par[x]); }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (sz[x] < sz[y]) swap(x, y);
    sz[x] += sz[y];
    par[y] = x;
  }
  bool areSame(int x, int y) { return find(x) == find(y); }
  int size(int x) { return sz[find(x)]; }
};
vector<vector<Edge>> minimumCostArborescence(vector<vector<Edge>> G) {
  const int INF = INT_MAX;
  int N = G.size();
  vector<Edge> minEdge(N, Edge(-1, -1, INF));
  for (int v = 0; v < N; v++)
    for (auto &e : G[v])
      if (minEdge[e.to].cost > e.cost) minEdge[e.to] = e;
  UnionFindTree uf(N);
  vector<int> isInC(N);
  for (int i = 0; i < N; i++) {
    if (minEdge[i].from == -1) continue;
    if (uf.areSame(minEdge[i].from, i)) {
      for (int j = 0; j < N; j++)
        if (uf.areSame(j, i)) isInC[j] = 1;
      break;
    } else {
      uf.unite(minEdge[i].from, i);
    }
  }
  if (find(isInC.begin(), isInC.end(), 1) == isInC.end()) {
    if (uf.size(0) != N) return vector<vector<Edge>>();
    vector<vector<Edge>> ret(N);
    for (int i = 0; i < N; i++)
      if (minEdge[i].from != -1) ret[minEdge[i].from].push_back(minEdge[i]);
    return ret;
  }
  vector<int> newIndex(N);
  for (int i = 0; i < N; i++)
    newIndex[i] = (i ? newIndex[i - 1] : -1) + (isInC[i] == 0);
  int n = newIndex[N - 1] + 2;
  vector<vector<Edge>> g(n);
  vector<int> oldIndex(n);
  Edge minC(-1, -1, INF);
  for (int i = 0; i < N; i++) {
    if (isInC[i]) {
      if (minC.cost > minEdge[i].cost) minC = minEdge[i];
      newIndex[i] = n - 1;
    } else {
      oldIndex[newIndex[i]] = i;
    }
  }
  for (int v = 0; v < N; v++)
    for (auto &e : G[v]) {
      int u = e.to;
      if (isInC[v] && isInC[u]) continue;
      if (!isInC[v] && isInC[u]) {
        g[newIndex[v]].push_back(Edge(newIndex[v], newIndex[u],
                                      e.cost + minC.cost - minEdge[u].cost,
                                      &e));
      } else {
        g[newIndex[v]].push_back(Edge(newIndex[v], newIndex[u], e.cost, &e));
      }
    }
  g = minimumCostArborescence(g);
  if (g.size() == 0) return vector<vector<Edge>>();
  vector<vector<Edge>> ret(N);
  for (int v = 0; v < n; v++) {
    for (auto &e : g[v]) {
      if (v != n - 1 && e.to == n - 1) minC = minEdge[e.prevEdge->to];
      ret[e.prevEdge->from].push_back(*e.prevEdge);
    }
  }
  for (int i = 0; i < N; i++)
    if (isInC[i] && minEdge[i].to != minC.to)
      ret[minEdge[i].from].push_back(minEdge[i]);
  return ret;
}
int minimumCostArborescence(vector<int> A, vector<int> B, vector<int> C) {
  int N =
      max(*max_element(A.begin(), A.end()), *max_element(B.begin(), B.end())) +
      1;
  vector<vector<Edge>> G(N);
  for (int i = 0; i < A.size(); i++) G[A[i]].push_back(Edge(A[i], B[i], C[i]));
  G = minimumCostArborescence(G);
  if (G.size() == 0) return -1;
  int ret = 0;
  for (int v = 0; v < N; v++)
    for (auto &e : G[v]) ret += e.cost;
  return ret;
}
signed main() {
  int N, M, r;
  scanf("%d%d%d", &N, &M, &r);
  vector<int> A(M), B(M), C(M);
  for (int i = 0; i < M; i++) scanf("%d%d%d", &A[i], &B[i], &C[i]);
  A.push_back(N);
  B.push_back(r);
  C.push_back(0);
  cout << minimumCostArborescence(A, B, C) << endl;
}
