#include <functional>
#include <memory>
#include <cassert>

template<class T, class E, class Compare = std::less<T>>
struct skew_heap {
	using F = std::function<T(T, E)>;
	using G = std::function<E(E, E)>;
	using value_type = T;
	using operator_type = E;
	using size_type = std::size_t;
	using const_reference = const value_type &;
private : 
	const Compare comp;
	const F f;
	const G g;
	const operator_type ie;
	size_type _size;

	struct node {
	public : 
		value_type value;
		operator_type lazy;
		std::unique_ptr<node> left, right;
		node (const value_type &x, const operator_type &e) :
			value(x), lazy(e), left(nullptr), right(nullptr) { }
	};

	using node_ptr = std::unique_ptr<node>;

	node_ptr root;

	node_ptr propagate (node_ptr x) {
		if (not x) return (std::move(x));
		if ((x->lazy) == ie) return (std::move(x));
		if (x->left) {
			(x->left->lazy) = g(x->left->lazy, x->lazy);
		}
		if (x->right) {
			(x->right->lazy) = g(x->right->lazy, x->lazy);
		}
		(x->value) = f(x->value, x->lazy);
		(x->lazy) = ie;
		return (std::move(x));
	}

	node_ptr meld (node_ptr a, node_ptr b) {
		a = propagate(std::move(a));
		b = propagate(std::move(b));
		if (not a) return (std::move(b));
		if (not b) return (std::move(a));
		if (comp((a->value), (b->value))) a.swap(b);
		(a->right) = meld(std::move(a->right), std::move(b));
		(a->right).swap(a->left);
		return (std::move(a));
	}

public : 

	explicit skew_heap (const F &f, const G &g, const operator_type &ie) : 
		f(f), g(g), comp(), ie(ie), _size(0), root(nullptr) { }

	explicit skew_heap (skew_heap&& rhs) noexcept :
		f(rhs.f), g(rhs.g), comp(rhs.comp), ie(rhs.ie), _size(rhs._size), root(std::move(rhs.root)) { }

	constexpr size_type size () const noexcept {
		return (_size);
	}

	constexpr bool empty () const noexcept {
		return (not _size);
	}

	constexpr const_reference top () {
		assert (not empty());
		root = propagate(std::move(root));
		return (root->value);
	}

	void pop () {
		assert(not empty());
		root = propagate(std::move(root)); _size--;
		root = meld(std::move(root->left), std::move(root->right));
	}

	void push (const value_type &x) {
		root = meld(std::move(root), std::make_unique<node>(node(x, ie)));
		_size++;
	}

	void clear () {
		while (not empty()) pop();
	}

	void add (const operator_type &x) {
		if (root) (root->lazy) = g(root->lazy, x);
	}

	void meld (skew_heap &rhs) {
		(this->_size) += (rhs._size); rhs._size = 0;
		(this->root) = meld(std::move(this->root), std::move(rhs.root));
	}

	void swap (skew_heap &rhs) {
		(this->root).swap(rhs.root);
		swap((this->_size), rhs._size);
	}

};

#include <vector>
#include <numeric>
#include <algorithm>

template<class T>
struct directed_minimum_spanning_tree {
	using value_type = T;
private :
	struct edge {
	public : 
		int from, to;
		value_type cost;
		edge (int from, int to, const value_type &cost) :
			from(from), to(to), cost(cost) { }
	};

	std::vector<edge> edges;
	std::vector<int> uf, par;

	bool unite (int x, int y) {
		x = root(x); y = root(y);
		if (x == y) return false;
		uf[x] = y; return true;
	}

	int root (int x) {
		return (uf[x] == x ? x : uf[x] = root(uf[x]));
	}

public :

	directed_minimum_spanning_tree (int n) : par(n), uf(n) { }

	void add_edge (int from, int to, const value_type &cost) {
		edges.emplace_back(from, to, cost);
	}

	value_type solve (int r = 0) {
		using data = std::pair<value_type, int>;
		using heap = skew_heap<data, value_type, std::greater<data>>;
		const int n = int(par.size());
		value_type sum_cost = 0;
		std::vector<heap> heaps;
		std::vector<int> order, status(n, 0), incoming(n, -1), prev_edge(edges.size());
		auto f1 = [](const data &a, const value_type &b) { return (data(a.first - b, a.second)); };
		auto f2 = [](const value_type &a, const value_type &b) { return (a + b); };
		for (int i = 0; i < n; i++) heaps.push_back(heap(f1, f2, 0));
		for (int i = 0; i < int(edges.size()); i++) heaps[edges[i].to].push(data(edges[i].cost, i));

		status[r] = 2; par[r] = r;
		std::iota(uf.begin(), uf.end(), 0);

		for (int s = 0; s < n; s++) if (status[s] == 0) {
			std::vector<int> seen, processed;
			
			for (int u = s, v, cycle = 0; status[u] != 2; u = root(v)) {
				status[u] = 1;
				processed.push_back(u);
				
				if (heaps[u].empty()) return -1;
				value_type cost;
				int i;
				std::tie(cost, i) = heaps[u].top();
				heaps[u].pop();
				const edge &e = edges[i];
				sum_cost += cost;
				heaps[u].add(cost);
				order.push_back(i);
				
				if (incoming[e.to] == -1) {
					incoming[e.to] = i;
				}
				
				while (cycle) {
					prev_edge[seen.back()] = i;
					seen.pop_back();
					cycle--;
				}
				
				seen.push_back(i);
				
				if (status[root(v = e.from)] == 1) {
					int w;
					heap buff(f1, f2, 0);
					do {
						w = processed.back();
						processed.pop_back();
						status[w] = 2;
						buff.meld(heaps[w]);
						cycle++;
					} while (unite(w, v));
					heaps[root(v)].meld(buff);
					status[root(v)] = 1;
				}
			}
			
			for (int i : processed) status[i] = 2;
		}

		std::reverse(order.begin(), order.end());
		std::vector<bool> used_edge(edges.size(), false);
		for (int i : order) if (not used_edge[i]) {
			const edge &e = edges[i];
			par[e.to] = e.from;
			for (int j = incoming[e.to]; j != i; j = prev_edge[j]) {
				used_edge[j] = true;
			}
		}
		
		return sum_cost;
	}

	const int& operator[] (int i) const {
		return (par[i]);
	}

};

#include <iostream>

int main() {
	int n, m, r;
	std::cin >> n >> m >> r;
	
	directed_minimum_spanning_tree<int> dmst(n);
	for (int i = 0; i < m; i++) {
		int s, t, w;
		std::cin >> s >> t >> w;
		dmst.add_edge(s, t, w);
	}
	
	std::cout << dmst.solve(r) << '\n';
	
	return 0;
}


Measured memory_bytes: 3296