#include <bits/stdc++.h>
using namespace std;
vector<int> graph[200007], cost[200007], graph2[200007];
vector<int> tree[200007], rg[200007], bucket[200007];
int sdom[200007], par[200007], dom[200007], dsu[200007], label[200007];
int arr[200007], rev[200007], T;
void dini(int node) {
  T = 0;
  for (int i = 0; i <= node; i++) {
    sdom[i] = par[i] = dom[i] = dsu[i] = label[i] = 0;
    arr[i] = rev[i] = 0;
    graph[i].clear();
    tree[i].clear();
    rg[i].clear();
    bucket[i].clear();
  }
}
int Find(int u, int x = 0) {
  if (u == dsu[u]) return x ? -1 : u;
  int v = Find(dsu[u], x + 1);
  if (v < 0) return u;
  if (sdom[label[dsu[u]]] < sdom[label[u]]) label[u] = label[dsu[u]];
  dsu[u] = v;
  return x ? v : label[u];
}
void Union(int u, int v) { dsu[v] = u; }
void dfs0(int u) {
  T++;
  arr[u] = T;
  rev[T] = u;
  label[T] = T;
  sdom[T] = T;
  dsu[T] = T;
  for (int i = 0; i < graph[u].size(); i++) {
    int w = graph[u][i];
    if (!arr[w]) dfs0(w), par[arr[w]] = arr[u];
    rg[arr[w]].push_back(arr[u]);
  }
}
void BuildTree(int src) {
  dfs0(src);
  int n = T;
  for (int i = n; i >= 1; i--) {
    for (int j = 0; j < rg[i].size(); j++)
      sdom[i] = min(sdom[i], sdom[Find(rg[i][j])]);
    if (i > 1) bucket[sdom[i]].push_back(i);
    for (int j = 0; j < bucket[i].size(); j++) {
      int w = bucket[i][j];
      int v = Find(w);
      if (sdom[v] == sdom[w])
        dom[w] = sdom[w];
      else
        dom[w] = v;
    }
    if (i > 1) Union(par[i], i);
  }
  for (int i = 2; i <= n; i++) {
    if (dom[i] != sdom[i]) dom[i] = dom[dom[i]];
    tree[rev[i]].push_back(rev[dom[i]]);
    tree[rev[dom[i]]].push_back(rev[i]);
  }
}
long long dstnc[200007];
void dijkastra(int src) {
  set<pair<long long, int> > st;
  int u, v;
  pair<long long, int> jora;
  memset(dstnc, -1, sizeof dstnc);
  dstnc[src] = 0;
  st.insert(make_pair(0, src));
  while (!st.empty()) {
    jora = *st.begin();
    st.erase(st.begin());
    u = jora.second;
    for (int i = 0; i < graph2[u].size(); i++) {
      v = graph2[u][i];
      if (dstnc[v] == -1 || dstnc[u] + cost[u][i] < dstnc[v]) {
        dstnc[v] = dstnc[u] + cost[u][i];
        st.insert(make_pair(dstnc[v], v));
      }
    }
  }
}
bool mflag[200007];
void make_graph(int u) {
  if (mflag[u]) return;
  mflag[u] = 1;
  int v;
  for (int i = 0; i < graph2[u].size(); i++) {
    v = graph2[u][i];
    if (dstnc[u] + cost[u][i] == dstnc[v]) {
      graph[u].push_back(v);
      make_graph(v);
    }
  }
}
int sub_node[200007], ans;
void dfs(int u, int p) {
  int v;
  sub_node[u] = 1;
  for (int i = 0; i < tree[u].size(); i++) {
    v = tree[u][i];
    if (v == p) continue;
    dfs(v, u);
    sub_node[u] += sub_node[v];
    ans = max(ans, sub_node[v]);
  }
}
int main() {
  int n, m, s, u, v, cst;
  scanf("%d %d %d", &n, &m, &s);
  for (int i = 0; i < m; i++) {
    scanf("%d %d %d", &u, &v, &cst);
    graph2[u].push_back(v);
    graph2[v].push_back(u);
    cost[u].push_back(cst);
    cost[v].push_back(cst);
  }
  dijkastra(s);
  dini(n);
  make_graph(s);
  BuildTree(s);
  dfs(s, s);
  printf("%d\n", ans);
  return 0;
}
