#include <bits/stdc++.h>
using namespace std;
template <class type>
inline const void read(type &in) {
  in = 0;
  char ch = getchar();
  while (ch < 48 || ch > 57) ch = getchar();
  while (ch > 47 && ch < 58)
    in = (in << 3) + (in << 1) + (ch & 15), ch = getchar();
}
const long long inf = 0x7f7f7f7f7f7f7f7f;
const int N = 2e5 + 10;
int n, m, s, ans;
vector<pair<int, int> > g[N];
long long dis[N];
bool vis[N];
int ind[N];
vector<int> in[N], out[N];
inline const void addedge(int u, int v) {
  in[v].push_back(u);
  ind[v]++;
  out[u].push_back(v);
}
inline const void dijkstra(int s) {
  memset(dis, 0x7f, sizeof(dis));
  priority_queue<pair<long long, int>, vector<pair<long long, int> >,
                 greater<pair<long long, int> > >
      q;
  q.push(make_pair(dis[s] = 0, s));
  while (!q.empty()) {
    int u = q.top().second, v;
    q.pop();
    if (vis[u]) continue;
    vis[u] = 1;
    for (vector<pair<int, int> >::iterator i = g[u].begin(); i != g[u].end();
         i++)
      if (dis[v = i->first] > dis[u] + i->second)
        q.push(make_pair(dis[v] = dis[u] + i->second, v));
  }
}
inline const void build() {
  for (int i = 1; i <= n; i++)
    for (vector<pair<int, int> >::iterator j = g[i].begin(); j != g[i].end();
         j++)
      if (dis[j->first] ^ inf && dis[j->first] == dis[i] + j->second)
        addedge(i, j->first);
}
class Link_Cut_Tree {
 private:
  struct tree {
    int fa, son[2], size, imagsize;
  } t[N];
  inline const bool identity(int p) { return t[t[p].fa].son[1] == p; }
  inline const bool nroot(int p) {
    return t[t[p].fa].son[0] == p || identity(p);
  }
  inline const void pushup(int p) {
    t[p].size = t[t[p].son[0]].size + t[t[p].son[1]].size + t[p].imagsize + 1;
  }
  inline const void rotate(int p) {
    const bool f = identity(p);
    int fa = t[p].fa, gfa = t[fa].fa, q = t[p].son[f ^ 1];
    if (nroot(fa)) t[gfa].son[identity(fa)] = p;
    t[t[p].son[f ^ 1] = fa].son[f] = q;
    t[t[t[q].fa = fa].fa = p].fa = gfa;
    pushup(fa);
  }
  inline const void splay(int p) {
    for (int fa; nroot(p); rotate(p))
      if (nroot(fa = t[p].fa)) rotate(identity(p) ^ identity(fa) ? p : fa);
    pushup(p);
  }
  inline const int access(int x) {
    int y = 0;
    for (; x; x = t[y = x].fa)
      splay(x), t[x].imagsize += t[t[x].son[1]].size,
          t[x].imagsize -= t[t[x].son[1] = y].size, pushup(x);
    return y;
  }
  inline const int findroot(int x) {
    access(x);
    splay(x);
    while (t[x].son[0]) x = t[x].son[0];
    splay(x);
    return x;
  }

 public:
  inline const void link(int x, int y) {
    splay(x);
    t[x].fa = y;
    access(y);
    splay(y);
    t[y].son[1] = x;
    pushup(y);
  }
  inline const int lca(int x, int y) {
    if (findroot(x) ^ findroot(y)) return 0;
    access(x);
    return access(y);
  }
  inline const int getsize(int x) {
    access(x);
    splay(x);
    return t[x].imagsize + 1;
  }
} lct;
inline const void toposort(int s) {
  queue<int> q;
  q.push(s);
  while (!q.empty()) {
    int u = q.front(), lca = -1;
    q.pop();
    for (vector<int>::iterator i = out[u].begin(); i != out[u].end(); i++)
      if (!--ind[*i]) q.push(*i);
    for (vector<int>::iterator i = in[u].begin(); lca && i != in[u].end(); i++)
      if (~lca)
        lca = lct.lca(lca, *i);
      else
        lca = *i;
    if (~lca && lca) lct.link(u, lca);
  }
}
int main() {
  read(n);
  read(m);
  read(s);
  for (int u, v, w; m--;)
    read(u), read(v), read(w), g[u].push_back(make_pair(v, w)),
        g[v].push_back(make_pair(u, w));
  dijkstra(s);
  build();
  toposort(s);
  for (int i = 1; i <= n; i++)
    if (i ^ s && dis[i] ^ inf) ans = max(ans, lct.getsize(i));
  printf("%d\n", ans);
  return 0;
}
