#include <bits/stdc++.h>
using namespace std;
constexpr int INF = numeric_limits<int>::max();
struct Edge {
  int from, to, cost;
  Edge(int f = 0, int t = 0, int c = 0) : from(f), to(t), cost(c) {}
  bool operator<(const Edge& other) { return this->cost < other.cost; }
};
struct Graph {
  int V, r;
  vector<Edge> edges;
  Graph() : V(0), r(0), edges(0) {}
  Graph(int n_v, int root, vector<Edge>& _edges)
      : V(n_v), r(root), edges(_edges) {}
};
pair<vector<int>, vector<int>> select_parents(int V, int r,
                                              const vector<Edge>& edges) {
  vector<int> parents(V, -1);
  vector<int> costs(V, INF);
  for (auto e : edges) {
    if (parents[e.to] == -1 or e.cost < costs[e.to]) {
      parents[e.to] = e.from;
      costs[e.to] = e.cost;
    }
  }
  parents[r] = r;
  return make_pair(parents, costs);
}
void track_back(int v, vector<int>& groups, vector<bool>& visited,
                const vector<int>& parents) {
  vector<int> hist;
  for (; not visited[v]; visited[v] = true, hist.push_back(v), v = parents[v])
    ;
  if (groups[v] == -1) groups[v] = v;
  int g = groups[v];
  while (not hist.empty() and hist.back() != g) {
    groups[hist.back()] = g;
    hist.pop_back();
  }
  if (not hist.empty()) hist.pop_back();
  if (not hist.empty()) g = hist.back();
  while (not hist.empty()) {
    groups[hist.back()] = g;
    hist.pop_back();
  }
}
vector<int> detect_cycles(int V, int r, const vector<int>& parents) {
  vector<int> groups(V, -1);
  vector<bool> visited(V, false);
  groups[r] = r;
  visited[r] = true;
  for (int v = 0; v < V; ++v) {
    if (v == r or visited[v]) continue;
    track_back(v, groups, visited, parents);
  }
  return groups;
}
int count_cycle_cost(int V, int r, const vector<int>& costs,
                     const vector<int>& groups) {
  int cycle_cost = 0;
  for (int v = 0; v < V; ++v) {
    if (groups[v] != r) cycle_cost += costs[v];
  }
  return cycle_cost;
}
Graph compress_cycle(int V, int r, const vector<Edge>& edges,
                     const vector<int>& costs, const vector<int>& groups) {
  vector<int> new_label(V, -1);
  int label = 0;
  for (int v = 0; v < V; ++v) {
    int g = groups[v];
    if (g == r) {
      new_label[v] = label;
      ++label;
    } else if (new_label[g] == -1) {
      new_label[g] = label;
      new_label[v] = label;
      ++label;
    } else {
      new_label[v] = new_label[g];
    }
  }
  Graph new_graph;
  for (auto& e : edges) {
    if (groups[e.to] == r) {
      new_graph.edges.emplace_back(new_label[e.from], new_label[e.to], e.cost);
    } else if (groups[e.from] != groups[e.to]) {
      assert(e.cost >= costs[e.to]);
      new_graph.edges.emplace_back(new_label[e.from], new_label[e.to],
                                   e.cost - costs[e.to]);
    }
  }
  new_graph.V = *max_element(begin(new_label), end(new_label)) + 1;
  new_graph.r = new_label[r];
  return new_graph;
}
int minCostArborescence(int V, int r, const vector<Edge>& edges) {
  auto result = select_parents(V, r, edges);
  auto parents = result.first;
  auto costs = result.second;
  auto groups = detect_cycles(V, r, parents);
  int cycle_cost = count_cycle_cost(V, r, costs, groups);
  if (cycle_cost == 0) {
    int cost = 0;
    for (int i = 0; i < V; ++i)
      if (i != r) cost += costs[i];
    return cost;
  } else {
    auto new_graph = compress_cycle(V, r, edges, costs, groups);
    return cycle_cost +
           minCostArborescence(new_graph.V, new_graph.r, new_graph.edges);
  }
}
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int V, E, r;
  cin >> V >> E >> r;
  vector<Edge> edges(E);
  for (auto& e : edges) cin >> e.from >> e.to >> e.cost;
  cout << minCostArborescence(V, r, edges) << endl;
  return 0;
}
