#include <bits/stdc++.h>
using namespace std;
const int maxN = 200001;
const long long INF = 1000000000000000LL;
struct Dominator_tree {
 private:
  vector<int>* G;
  vector<int> G_inv[maxN], bucket[maxN];
  int in_ctr, in[maxN], in_inv[maxN], sdom[maxN], idom[maxN], parent[maxN],
      anc[maxN], F[maxN];
  inline void relax(int& a, int b) { a = min(a, b); }
  int find(int v, bool is_rec_root = true) {
    if (anc[v] == v) return (is_rec_root ? v : 0);
    int u = find(anc[v], false);
    if (u == 0) return F[v];
    if (sdom[u] < sdom[F[v]]) F[v] = u;
    anc[v] = anc[anc[v]];
    return F[v];
  }
  void dfs(int v) {
    in[v] = ++in_ctr, in_inv[in_ctr] = v;
    for (int u : G[v]) {
      if (in[u] == 0) dfs(u), parent[in[u]] = in[v];
      G_inv[in[u]].push_back(in[v]);
    }
  }
  void clear(int n) {
    for (int i = 1; i <= in_ctr; i++) G_inv[i].resize(0), bucket[i].resize(0);
    fill(idom, idom + in_ctr + 1, 0);
    fill(F, F + in_ctr + 1, 0);
    fill(in, in + n + 1, 0);
    in_ctr = 0;
  }

 public:
  void gen_dom_tree(vector<int>* g, int n, int s, vector<int>* res) {
    G = g;
    dfs(s);
    for (int i = 1; i <= in_ctr; i++) anc[i] = sdom[i] = i;
    for (int i = in_ctr; i > 1; i--) {
      for (int v : G_inv[i]) relax(sdom[i], sdom[find(v)]);
      bucket[sdom[i]].push_back(i);
      int fath = parent[i];
      anc[i] = fath, F[i] = i;
      for (int v : bucket[fath]) {
        int u = find(v);
        idom[v] = (sdom[u] == sdom[v] ? fath : u);
      }
      bucket[fath].resize(0);
    }
    for (int i = 2; i <= in_ctr; i++) {
      int& id = idom[i];
      if (id != sdom[i]) id = idom[id];
      res[in_inv[id]].push_back(in_inv[i]);
    }
    clear(n);
  }
} compute;
vector<pair<int, int> > G[maxN];
vector<int> sp_dag[maxN], dom_tree[maxN];
priority_queue<pair<long long, int> > H;
long long dist[maxN];
int n, res;
void Dijkstra(int source) {
  fill(dist + 1, dist + n + 1, INF);
  dist[source] = 0;
  H.push(make_pair(0, source));
  while (!H.empty()) {
    long long d = -H.top().first;
    int v = H.top().second;
    H.pop();
    if (dist[v] != d) continue;
    for (int i = 0; i < G[v].size(); i++) {
      int u = G[v][i].first, edge = G[v][i].second;
      if (dist[u] > d + edge) {
        dist[u] = d + edge;
        H.push(make_pair(-dist[u], u));
      }
    }
  }
}
int dfs(int v) {
  int sz = 1;
  for (int u : dom_tree[v]) {
    int sz_temp = dfs(u);
    res = max(res, sz_temp);
    sz += sz_temp;
  }
  return sz;
}
int main() {
  int m, s;
  scanf("%d%d%d", &n, &m, &s);
  while (m--) {
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    G[a].push_back(make_pair(b, c));
    G[b].push_back(make_pair(a, c));
  }
  Dijkstra(s);
  for (int v = 1; v <= n; v++) {
    for (int j = 0; j < G[v].size(); j++) {
      int u = G[v][j].first, e = G[v][j].second;
      if (dist[u] == dist[v] + e) sp_dag[v].push_back(u);
    }
  }
  compute.gen_dom_tree(sp_dag, n, s, dom_tree);
  dfs(s);
  printf("%d\n", res);
  return 0;
}
