#include <iostream>
#include <queue>
#define INF 1000000000
#define NV 100000
using namespace std;
class edge
{
  public:
  int t;
  int d;
  edge *nextedge;
  edge(int,int);
};

edge::edge(int tt,int dd)
{
  t=tt;
  d=dd;
  nextedge=NULL;
}

class vertice
{
  public:
  edge *firstedge;
  void create_edge(int,int);
};

void vertice::create_edge(int t,int d)
{
  edge *newedge=new edge(t,d);
  if(firstedge==NULL)
    firstedge=newedge;
  else
  {
    edge *tmp=firstedge;
    while(tmp->nextedge!=NULL)
    {
      tmp=tmp->nextedge;
    }
    tmp->nextedge=newedge;
  }
}

class source
{
  public:
  int n;
  int dis;
  friend bool operator<(source,source);
};

bool operator<(source a, source b)
{
  return a.dis>b.dis;
}

int main()
{
  int v,e,r;
  cin>>v>>e>>r;
  source weight[v];
  vertice vertices[v];
  for(int i=0;i<v;i++)
  {
    vertices[i].firstedge=NULL;
    weight[i].n=i;
    weight[i].dis=INF;
  }
  for(int i=0;i<e;i++)
  {
    int s,t,d;
    cin>>s>>t>>d;
    vertices[s].create_edge(t,d);
  }
  weight[r].dis=0;
  int current_vertex=r;
  priority_queue<source> queue;
  queue.push(weight[r]);
  while(queue.size()!=0)
  {
    source del=queue.top();
    queue.pop();
    current_vertex=del.n;
    edge *neighbor=vertices[current_vertex].firstedge;
    while(neighbor!=NULL)
    {
      int vn=neighbor->t;
      if(weight[vn].dis>weight[current_vertex].dis+neighbor->d)
      {
        weight[vn].dis=weight[current_vertex].dis+neighbor->d;
        queue.push(weight[vn]);
      }
      neighbor=neighbor->nextedge;
    }
  }
  for(int i=0;i<v;i++)
    if(weight[i].dis>=INF)
      cout<<"INF"<<endl;
    else
      cout<<weight[i].dis<<endl;
}
#include <vector>
#include <algorithm>
#include <iostream>
#include <queue>
#include <set>
#define INF 100000000
#define ll long long
using namespace std;

class Bit{
private:
  ll *par, *rk, size;
public:
  Bit(ll size){
    par = new ll[size];
    rk = new ll[size];
    for(ll i = 0; i < size; i++){
      par[i] = i;
      rk[i] = 0;
    }
  }
  ll find(ll x){
    if(x == par[x])
      return x;
    else
      return par[x] = find(par[x]);
  }
  void merge(ll x,ll y){
    x = find(x);
    y = find(y);
    if(rk[x] > rk[y]){
      par[y] = x;
    }else if(rk[x] < rk[y]){
      par[x] = y;
    }else{
      par[y] = x;
      rk[x]++;
    }
  }
  bool same(ll x, ll y){
    return find(x) == find(y);
  }
};
int main(){
  ll V, E;
  cin >> V >> E;
  Bit bit(V);
  priority_queue< pair<ll, pair<ll,ll> >, vector< pair<ll, pair<ll,ll> > >, greater< pair<ll, pair<ll,ll> > > > pq;
  for(ll i = 0; i < E; i++){
    ll s,t,w;
    cin >> s >> t >> w;
    pq.push(make_pair(w, make_pair(s,t)));
  }
  ll cost = 0;
  for(ll i = 0; i < V - 1; i++){
    while(1){
      if(bit.same(pq.top().second.first, pq.top().second.second)){
	pq.pop();
      }else{
	break;
      }
    }
    bit.merge(pq.top().second.first, pq.top().second.second);
    cost += pq.top().first;
  }
  cout << cost << endl;
  return 0;
}