#include <bits/stdc++.h>
using namespace std;
vector<struct EdgeStruct> incoming[2 * 100000];
struct UFVal {
  int rep[2 * 100000];
  int val[2 * 100000];
  int valatroot[2 * 100000];
  int upto;
  UFVal() {
    upto = 100000;
    for (int i = 0; i < 2 * 100000; i++) rep[i] = i;
  }
  int findrep(int a) {
    if (rep[a] == a) return a;
    int b = rep[a];
    rep[a] = findrep(b);
    val[a] += val[b];
    return rep[a];
  }
  bool connected(int a, int b) { return findrep(a) == findrep(b); }
  void merge(int a, int b) {
    a = findrep(a);
    b = findrep(b);
    assert(a != b);
    rep[a] = b;
  }
  void addval(int a, int val) {
    a = findrep(a);
    valatroot[a] += val;
  }
  int findval(int a) {
    int b = findrep(a);
    return val[a] + valatroot[b];
  }
};
struct UF {
  int rep[100000];
  UF() {
    for (int i = 0; i < 100000; i++) rep[i] = i;
  }
  int findrep(int a) {
    if (rep[a] == a) return a;
    return rep[a] = findrep(rep[a]);
  }
  bool connected(int a, int b) { return findrep(a) == findrep(b); }
  void merge(int a, int b) { rep[findrep(a)] = findrep(b); }
};
UFVal supernodes;
UF trees;
struct EdgeStruct {
  int u, v;
  int weight;
  int val() { return weight - supernodes.findval(v); }
  bool operator==(const EdgeStruct e) const {
    return e.u == u && v == e.v && weight == e.weight;
  }
};
int n, m;
int ans;
queue<int> roots;
struct EdgeStruct par[2 * 100000];
int main() {
  scanf("%d%d", &n, &m);
  int r;
  scanf("%d", &r);
  for (int i = 0; i < m; i++) {
    int a, b;
    int c;
    scanf("%d%d%d", &a, &b, &c);
    struct EdgeStruct e;
    e.u = a;
    e.v = b;
    e.weight = c;
    incoming[b].push_back(e);
  }
  for (int i = 0; i < n; i++) {
    if (i != r) roots.push(i);
  }
  while (!roots.empty()) {
    int a = roots.front();
    roots.pop();
    if (a != supernodes.findrep(a)) continue;
    struct EdgeStruct e;
    while (true) {
      if (incoming[a].empty()) assert(false);
      e = incoming[a][0];
      for (int i = 1; i < incoming[a].size(); i++) {
        if (incoming[a][i].val() < e.val()) e = incoming[a][i];
      }
      for (int i = 0; i < incoming[a].size(); i++) {
        if (incoming[a][i] == e) {
          incoming[a].erase(incoming[a].begin() + i,
                            incoming[a].begin() + i + 1);
          break;
        }
      }
      if (!supernodes.connected(e.u, e.v)) break;
    }
    ans += e.val();
    par[a] = e;
    if (trees.findrep(e.u) != trees.findrep(e.v)) {
      trees.merge(e.u, e.v);
    } else {
      struct EdgeStruct mxedge = e;
      int b = supernodes.findrep(e.u);
      while (b != a) {
        if (par[b].val() > mxedge.val()) mxedge = par[b];
        b = supernodes.findrep(par[b].u);
      }
      ans -= mxedge.val();
      int s = supernodes.upto++;
      b = supernodes.findrep(e.u);
      while (supernodes.findrep(b) != s) {
        supernodes.addval(b, par[b].val() - mxedge.val());
        for (auto c : incoming[b]) {
          incoming[s].push_back(c);
        }
        supernodes.merge(b, s);
        b = supernodes.findrep(par[b].u);
      }
      roots.push(s);
    }
  }
  printf("%d\n", ans);
}
