#include <bits/stdc++.h>
using namespace std;
template <class T, class second>
ostream& operator<<(ostream& s, pair<T, second>& p) {
  s << '{' << p.first << ", " << p.second << '}';
  return s;
}
template <class T>
ostream& operator<<(ostream& s, vector<T>& v) {
  if (v.empty()) {
    s << "[]";
    return s;
  }
  s << '[';
  for (int i = 0; i < v.size() - 1; i++) {
    s << v[i] << ", ";
  }
  s << v.back() << ']';
  return s;
}
struct edg {
  int v, w;
  edg() { v = w = 0; }
  edg(const int _v, const int _w) {
    v = _v;
    w = _w;
  }
};
int n, m, second;
int und[200005];
int hei[200005];
int par[200005][20];
bool vis[200005];
int64_t dist[200005];
vector<edg> adj[200005];
vector<int> adj3[200005];
vector<int> adj2[200005], radj[200005];
const int64_t inf = INT64_MAX >> 4;
inline void dijkstra() {
  fill(dist, dist + n + 1, inf);
  dist[second] = 0;
  priority_queue<pair<int64_t, int64_t>> pq;
  pq.push({0, second});
  while (!pq.empty()) {
    auto [d, v] = pq.top();
    pq.pop();
    if (vis[v]) {
      continue;
    }
    vis[v] = true;
    d = -d;
    for (auto x : adj[v]) {
      const int64_t rd = d + x.w;
      if (rd < dist[x.v]) {
        dist[x.v] = rd;
        pq.push({-rd, x.v});
      }
    }
  }
}
inline int lca(int a, int b) {
  if (hei[a] < hei[b]) {
    swap(a, b);
  }
  int diff = hei[a] - hei[b];
  for (int i = 0; i < 20; i++) {
    if ((diff >> i) & 1) {
      a = par[a][i];
    }
  }
  assert(a);
  assert(b);
  if (a == b) {
    return a;
  }
  assert(hei[a] == hei[b]);
  for (int i = 20 - 1; i >= 0; i--) {
    if (par[a][i] != par[b][i]) {
      a = par[a][i];
      b = par[b][i];
    }
  }
  assert(hei[a] == hei[b]);
  assert(par[a][0] == par[b][0]);
  assert(par[a][0]);
  return par[a][0];
}
int dfs(int v) {
  int sz = 1;
  for (auto x : adj3[v]) {
    sz += dfs(x);
  }
  return und[v] = sz;
}
int main() {
  scanf("%d%d%d", &n, &m, &second);
  vector<array<int, 3>> edges;
  for (int i = 1; i <= m; i++) {
    int a, b, w;
    scanf("%d%d%d", &a, &b, &w);
    adj[a].push_back(edg(b, w));
    adj[b].push_back(edg(a, w));
    edges.push_back(array<int, 3>{a, b, w});
  }
  dijkstra();
  for (int i = 0; i < m; i++) {
    const auto [a, b, w] = edges[i];
    if ((dist[a] + w) == dist[b]) {
      adj2[a].push_back(b);
      radj[b].push_back(a);
    }
    if ((dist[b] + w) == dist[a]) {
      adj2[b].push_back(a);
      radj[a].push_back(b);
    }
  }
  vector<int> tsort;
  {
    queue<int> dz;
    vector<int> degs(n + 1, 0);
    for (int i = 1; i <= n; i++) {
      if (dist[i] < inf) {
        degs[i] = adj2[i].size();
        if (degs[i] == 0) {
          dz.push(i);
        }
      } else {
        degs[i] = INT32_MAX;
      }
    }
    while (!dz.empty()) {
      int v = dz.front();
      dz.pop();
      tsort.push_back(v);
      for (auto x : radj[v]) {
        degs[x]--;
        if (degs[x] == 0) {
          dz.push(x);
        }
      }
    }
    reverse(tsort.begin(), tsort.end());
    assert(tsort[0] == second);
    hei[second] = 1;
  }
  for (int i = 1; i < tsort.size(); i++) {
    int v = tsort[i];
    assert(radj[v].size());
    int l = radj[v][0];
    for (int i = 1; i < radj[v].size(); i++) {
      l = lca(l, radj[v][i]);
    }
    adj3[l].push_back(v);
    par[v][0] = l;
    hei[v] = hei[l] + 1;
    for (int i = 1; i < 20; i++) {
      par[v][i] = par[par[v][i - 1]][i - 1];
    }
  }
  dfs(second);
  int mx = 0;
  for (int i = 1; i <= n; i++) {
    if (i == second) {
      continue;
    }
    mx = max(mx, und[i]);
  }
  printf("%d\n", mx);
  return 0;
}
