#include <bits/stdc++.h>

#define _overload(_1,_2,_3,name,...) name
#define _rep(i,n) _range(i,0,n)
#define _range(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload(__VA_ARGS__,_range,_rep,)(__VA_ARGS__)

#define _rrep(i,n) _rrange(i,n,0)
#define _rrange(i,a,b) for(int i=int(a)-1;i>=int(b);--i)
#define rrep(...) _overload(__VA_ARGS__,_rrange,_rrep,)(__VA_ARGS__)

#define _all(arg) begin(arg),end(arg)
#define uniq(arg) sort(_all(arg)),(arg).erase(unique(_all(arg)),end(arg))
#define getidx(ary,key) lower_bound(_all(ary),key)-begin(ary)
#define clr(a,b) memset((a),(b),sizeof(a))
#define bit(n) (1LL<<(n))
#define popcount(n) (__builtin_popcountll(n))

using namespace std;

template<class T>bool chmax(T &a, const T &b) { return (a<b)?(a=b,1):0;}
template<class T>bool chmin(T &a, const T &b) { return (b<a)?(a=b,1):0;}

using ll=long long;
using R=long double;
const R EPS=1e-9; // [-1000,1000]->EPS=1e-8 [-10000,10000]->EPS=1e-7
inline int sgn(const R& r){return(r > EPS)-(r < -EPS);}
inline R sq(R x){return sqrt(max<R>(x,0.0));}

const int dx[8]={1,0,-1,0,1,-1,-1,1};
const int dy[8]={0,1,0,-1,1,1,-1,-1};

// Problem Specific Parameter:

// Description: ??£?????°??????????????????????°?????????¨?????¨
// TimeComplexity: $ \mathcal{O}(E \log V) $
// Verifyed: AOJ GRL_2_A
// Required: Union-Find

// Description: ??°??????????????????(?????????????°??????¨???)
// Verifyed: Many Diffrent Problem 

//Appropriately Changed
using edge=struct{int to,cost;};
using G=vector<vector<edge>>;

//Appropriately Changed
void add_edge(G &graph,int from,int to,int cost){ 
	graph[from].push_back({to,cost});
}

auto chuliu(const G &graph,int root){
	using W=int;
	const W inf=1<<28;
	
	const int n=graph.size();

	vector<int> cost(n,inf),pv(n);

	rep(v,n) for(auto &e:graph[v]){
		if(chmin(cost[e.to],e.cost)) 
			pv[e.to]=v;
	}


	bool term=true;
	vector<int> comp(n,-1),used(n,-1);
	
	rep(v,n){
		if(used[v]!= -1 or cost[v]==inf or v==root) continue;

		int cur=used[v]=v;
		for(cur=pv[cur]; cur!=root && used[cur] == -1; cur=pv[cur]) used[cur]=v;

		if(used[cur]==v){
			term=false,comp[cur]=cur;	
			for(int w=pv[cur]; w != cur; w = pv[w]) comp[w]=cur;
			break;
		}
	}

	G ret(n);
	if(term){
		rep(v,n){
			//cout << cost[v] << endl;
			if(v!=root and cost[v]!=inf)
				add_edge(ret,pv[v],v,cost[v]);
		}
		//cout << "OK" << endl;
		return ret;
	}

	const int nroot=(comp[root]==-1)?root:comp[root];
	G ngraph(n);
	using memo=tuple<int,int,int>;
	map<memo,memo> dict;

	rep(v,n){
		for(auto &e:graph[v]){			
			int a=v,b=e.to,c=e.cost;
			if(comp[a]!=-1) a=comp[a];
			if(comp[b]!=-1) c-=cost[b],b=comp[b];
			if(a==b) continue;
			dict[memo(a,b,c)]=memo(v,e.to,e.cost);
			add_edge(ngraph,a,b,c);
		}
	}
	
	auto ntree=chuliu(ngraph,nroot);

	int unuse=-1;
	rep(v,n){
		for(auto &e:ntree[v]){
			int a,b,c;
			tie(a,b,c)=dict[memo(v,e.to,e.cost)];
			if(comp[b]!=-1) unuse=b;
			add_edge(ret,a,b,c);
		}
	}

	rep(v,n){
		if(comp[v]==-1 or v==unuse) continue;
		add_edge(ret,pv[v],v,cost[v]); 
	}
	
	return ret;
}

int main(void){
	int v,e,r;
	cin >> v >> e >> r;
	G graph(v);
	rep(i,e){
		int a,b,w;
		cin >> a >> b >> w;
		add_edge(graph,a,b,w);
	}

	auto tree=chuliu(graph,r);
	int ans=0;
	rep(i,v) for(auto &e:tree[i]) ans+=e.cost;
	cout << ans << endl;
	return 0;
}

Measured memory_bytes: 4932