// EDIT YOUR TEMPLATE AT ~/.cftool/template.cpp

#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef pair<int, int> ii;

const int N = 1e6/2;
int n, m, s;
vector<ii> adj[N];
vector<int> tree[N];

// 0 -indexed
template<typename T = int>
struct MinDsu{
  vector<int> r;
  vector<T> best;
  MinDsu(int n = 0){
    r = vector<int>(n); iota(r.begin(), r.end(), 0);
    best = vector<T>(n);
  }

  int find(int u) {
    if (r[u] == u)
      return u;
    else {
      int v = find(r[u]);
      if (best[r[u]] < best[u]) best[u] = best[r[u]];
      return r[u] = v;
    }
  }

  T eval(int u){ find(u); return best[u]; }
  void link(int p, int u) { r[u] = p; }
  void set(int u, T x) { best[u] = x; }
};

struct DominatorTree{
  typedef vector<vector<int>> Graph;
  vector<int> semi, dom, parent, st, from;
  Graph succ, pred, bucket;
  int r, n, tempo;

  void dfs(int u, int p){
    semi[u] = u;
    from[st[u] = tempo++] = u;
    parent[u] = p;
    for (int v : succ[u]) {
      pred[v].push_back(u);
      if (semi[v] == -1) { dfs(v, u); }
    }
  }

  void build(){
    n = succ.size();
    dom.assign(n, -1);
    semi.assign(n, -1);
    parent.assign(n, -1);
    st.assign(n, 0);
    from.assign(n, -1);
    pred = Graph(n, vector<int>());
    bucket = Graph(n, vector<int>());
    MinDsu<pair<int,int>> dsu(n);
    tempo = 0;

    dfs(r, r);
    for(int i = 0; i < n; i++) dsu.set(i, make_pair(st[i],  i));

    for (int i = tempo - 1; i; i--) {
      int u = from[i];
      for (int v : pred[u]) {
        int w = dsu.eval(v).second;
        if (st[semi[w]] < st[semi[u]]) { semi[u] = semi[w]; }
      }
      dsu.set(u, make_pair(st[semi[u]], u));
      bucket[semi[u]].push_back(u);
      dsu.link(parent[u], u);
      for(int v : bucket[parent[u]]) {
        int w = dsu.eval(v).second;
        dom[v] = semi[w] == parent[u] ? parent[u] : w;
      }
      bucket[parent[u]].clear();
    }
    for (int i = 1; i < tempo; i++) {
      int u = from[i];
      if (dom[u] != semi[u]) dom[u] = dom[dom[u]];
    }
  }

  DominatorTree(const Graph & g, int s) : succ(g), r(s) {
    build();
  }

};

struct Edge {
  int v, next;
} e[15 * N];
int sz;

struct Graph {
  int adj[N];
  void add(int u, int v) {
    sz++;
    e[sz].next = adj[u];
    e[sz].v = v;
    adj[u] = sz;
  }
  void clear(int n) {
    for (int i = 0; i < n; i++) adj[i] = 0;
  }
} succ, pred, bucket;

int from[N], st[N], nd[N];
int tempo;
int semi[N], dom[N], parent[N];
// dsu
int root[N], best[N];
int find(int u) {
  if (root[u] == u)
    return u;
  else {
    int v = find(root[u]);
    if (st[semi[best[root[u]]]] < st[semi[best[u]]]) best[u] = best[root[u]];
    return root[u] = v;
  }
}
void dfs(int u, int p) {
  semi[u] = u;
  from[st[u] = tempo++] = u;
  parent[u] = p;
  for (int k = succ.adj[u]; k; k = e[k].next) {
    int v = e[k].v;
    if (semi[v] == -1) { dfs(v, u); }
  }
}
// suppose 0-indexed
void compute(int n, int r) {
  bucket.clear(n);
  tempo = 0;
  for (int i = 0; i < n; i++) { root[i] = i, best[i] = i, dom[i] = semi[i] = -1; }
  dfs(r, r);
  for (int i = tempo - 1; i; i--) {
    int u = from[i];
    for (int k = pred.adj[u]; k; k = e[k].next) {
      int v = e[k].v;
      if (semi[v] == -1) continue;
      find(v);
      int w = best[v];
      if (st[semi[w]] < st[semi[u]]) { semi[u] = semi[w]; }
    }
    bucket.add(semi[u], u);
    root[u] = parent[u];
    for (int k = bucket.adj[parent[u]]; k; k = e[k].next) {
      int v = e[k].v;
      find(v);
      int w = best[v];
      dom[v] = semi[w] == parent[u] ? parent[u] : w;
    }
    bucket.adj[parent[u]] = 0;
  }
  for (int i = 1; i < tempo; i++) {
    int u = from[i];
    if (dom[u] != semi[u]) dom[u] = dom[dom[u]];
  }
}

struct State{
  int vert, dist;
  bool operator<(const State & rhs) const {
    return dist > rhs.dist;
  }
};

vector<vector<int>> g;

void dijkstra(){
  vector<int> dist(n, 1e16);
  priority_queue<State> pq;
  dist[s] = 0;
  pq.push({s, 0});

  while(!pq.empty()){
    State st = pq.top();
    pq.pop();

    if(st.dist != dist[st.vert]) continue;

    for(ii e : adj[st.vert]){
      if(e.second + st.dist < dist[e.first]){
        dist[e.first] = e.second + st.dist;
        pq.push({e.first, dist[e.first]});
      }
    }
  }

  for(int i = 0; i < n; i++){
    for(ii e : adj[i]){
      if(dist[i] + e.second == dist[e.first])
        succ.add(i, e.first), pred.add(e.first, i), g[i].push_back(e.first);
    }
  }
}

int ans;

int32_t main(){

  cin >> n >> m >> s;
  s--;

  succ.clear(n);
  pred.clear(n);

  for(int i = 0; i < n; i++){
    int u, v, w;
    cin >> u >> v >> w;
    u--, v--;
    adj[u].push_back(ii(v, w));
    adj[v].push_back(ii(u, w));
  }

  g.assign(n, vector<int>());
  dijkstra();
  DominatorTree dt(g, s);

  vector<int> subsz(n, 1);
  for(int i = dt.tempo-1; i; i--){
    int u = dt.from[i];
    if(dt.dom[u] == s) ans = max(ans, subsz[u]);
    else subsz[dt.dom[u]] += subsz[u];
  }

  cout << ans << endl;
}


// EDIT YOUR TEMPLATE AT ~/.cftool/template.cpp

#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef pair<int, int> ii;

const int N = 1e6/2;
int n, m, s;
vector<ii> adj[N];
vector<int> tree[N];

struct Edge {
  int v, next;
} e[15 * N];
int sz;

struct Graph {
  int adj[N];
  void add(int u, int v) {
    sz++;
    e[sz].next = adj[u];
    e[sz].v = v;
    adj[u] = sz;
  }
  void clear(int n) {
    for (int i = 0; i < n; i++) adj[i] = 0;
  }
} succ, pred, bucket;

int from[N], st[N], nd[N];
int tempo;
int semi[N], dom[N], parent[N];
// dsu
int root[N], best[N];
int find(int u) {
  if (root[u] == u)
    return u;
  else {
    int v = find(root[u]);
    if (st[semi[best[root[u]]]] < st[semi[best[u]]]) best[u] = best[root[u]];
    return root[u] = v;
  }
}
void dfs(int u, int p) {
  semi[u] = u;
  from[st[u] = tempo++] = u;
  parent[u] = p;
  for (int k = succ.adj[u]; k; k = e[k].next) {
    int v = e[k].v;
    if (semi[v] == -1) { dfs(v, u); }
  }
}
// suppose 0-indexed
void compute(int n, int r) {
  bucket.clear(n);
  tempo = 0;
  for (int i = 0; i < n; i++) { root[i] = i, best[i] = i, dom[i] = semi[i] = -1; }
  dfs(r, r);
  for (int i = tempo - 1; i; i--) {
    int u = from[i];
    for (int k = pred.adj[u]; k; k = e[k].next) {
      int v = e[k].v;
      if (semi[v] == -1) continue;
      find(v);
      int w = best[v];
      if (st[semi[w]] < st[semi[u]]) { semi[u] = semi[w]; }
    }
    //best[u]=u;
    bucket.add(semi[u], u);
    root[u] = parent[u];
    for (int k = bucket.adj[parent[u]]; k; k = e[k].next) {
      int v = e[k].v;
      find(v);
      int w = best[v];
      dom[v] = st[semi[w]] < st[semi[v]] ? w : parent[u];
    }
    bucket.adj[parent[u]] = 0;
  }
  for (int i = 1; i < tempo; i++) {
    int u = from[i];
    if (dom[u] != semi[u]) dom[u] = dom[dom[u]];
  }
}

struct State{
  int vert, dist;
  bool operator<(const State & rhs) const {
    return dist > rhs.dist;
  }
};

void dijkstra(){
  vector<int> dist(n, 1e16);
  priority_queue<State> pq;
  dist[s] = 0;
  pq.push({s, 0});

  while(!pq.empty()){
    State st = pq.top();
    pq.pop();

    if(st.dist != dist[st.vert]) continue;

    for(ii e : adj[st.vert]){
      if(e.second + st.dist < dist[e.first]){
        dist[e.first] = e.second + st.dist;
        pq.push({e.first, dist[e.first]});
      }
    }
  }

  for(int i = 0; i < n; i++){
    for(ii e : adj[i]){
      if(dist[i] + e.second == dist[e.first])
        succ.add(i, e.first), pred.add(e.first, i);
    }
  }
}

int ans;

int32_t main(){

  cin >> n >> m >> s;
  s--;

  succ.clear(n);
  pred.clear(n);

  for(int i = 0; i < n; i++){
    int u, v, w;
    cin >> u >> v >> w;
    u--, v--;
    adj[u].push_back(ii(v, w));
    adj[v].push_back(ii(u, w));
  }

  dijkstra();
  compute(n, s);

  vector<int> subsz(n, 1);
  for(int i = tempo-1; i; i--){
    int u = from[i];
    if(dom[u] == s) ans = max(ans, subsz[u]);
    else subsz[dom[u]] += subsz[u];
  }

  cout << ans << endl;
}


// EDIT YOUR TEMPLATE AT ~/.cftool/template.cpp

#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef pair<int, int> ii;

const int N = 1e6/2;
int n, m, s;
vector<ii> adj[N];
vector<int> tree[N];

struct Edge {
  int v, next;
} e[15 * N];
int sz;

struct Graph {
  int adj[N];
  void add(int u, int v) {
    sz++;
    e[sz].next = adj[u];
    e[sz].v = v;
    adj[u] = sz;
  }
  void clear(int n) {
    for (int i = 0; i < n; i++) adj[i] = 0;
  }
} succ, pred, bucket;

int from[N], st[N], nd[N];
int tempo;
int semi[N], dom[N], parent[N];
// dsu
int root[N], best[N];
int find(int u) {
  if (root[u] == u)
    return u;
  else {
    int v = find(root[u]);
    if (st[semi[best[root[u]]]] < st[semi[best[u]]]) best[u] = best[root[u]];
    return root[u] = v;
  }
}
void dfs(int u, int p) {
  semi[u] = u;
  from[st[u] = tempo++] = u;
  parent[u] = p;
  for (int k = succ.adj[u]; k; k = e[k].next) {
    int v = e[k].v;
    if (semi[v] == -1) { dfs(v, u); }
  }
}
// suppose 0-indexed
void compute(int n, int r) {
  bucket.clear(n);
  tempo = 0;
  for (int i = 0; i < n; i++) { root[i] = i, best[i] = i, dom[i] = semi[i] = -1; }
  dfs(r, r);
  for (int i = tempo - 1; i; i--) {
    int u = from[i];
    for (int k = pred.adj[u]; k; k = e[k].next) {
      int v = e[k].v;
      if (semi[v] == -1) continue;
      find(v);
      int w = best[v];
      if (st[semi[w]] < st[semi[u]]) { semi[u] = semi[w]; }
    }
    bucket.add(semi[u], u);
    root[u] = parent[u];
    for (int k = bucket.adj[parent[u]]; k; k = e[k].next) {
      int v = e[k].v;
      find(v);
      int w = best[v];
      dom[v] = semi[w] == parent[u] ? parent[u] : w;
    }
    bucket.adj[parent[u]] = 0;
  }
  for (int i = 1; i < tempo; i++) {
    int u = from[i];
    if (dom[u] != semi[u]) dom[u] = dom[dom[u]];
  }
}

struct State{
  int vert, dist;
  bool operator<(const State & rhs) const {
    return dist > rhs.dist;
  }
};

void dijkstra(){
  vector<int> dist(n, 1e16);
  priority_queue<State> pq;
  dist[s] = 0;
  pq.push({s, 0});

  while(!pq.empty()){
    State st = pq.top();
    pq.pop();

    if(st.dist != dist[st.vert]) continue;

    for(ii e : adj[st.vert]){
      if(e.second + st.dist < dist[e.first]){
        dist[e.first] = e.second + st.dist;
        pq.push({e.first, dist[e.first]});
      }
    }
  }

  for(int i = 0; i < n; i++){
    for(ii e : adj[i]){
      if(dist[i] + e.second == dist[e.first])
        succ.add(i, e.first), pred.add(e.first, i);
    }
  }
}

int ans;

int32_t main(){

  cin >> n >> m >> s;
  s--;

  succ.clear(n);
  pred.clear(n);

  for(int i = 0; i < n; i++){
    int u, v, w;
    cin >> u >> v >> w;
    u--, v--;
    adj[u].push_back(ii(v, w));
    adj[v].push_back(ii(u, w));
  }

  dijkstra();
  compute(n, s);

  vector<int> subsz(n, 1);
  for(int i = tempo-1; i; i--){
    int u = from[i];
    if(dom[u] == s) ans = max(ans, subsz[u]);
    else subsz[dom[u]] += subsz[u];
  }

  cout << ans << endl;
}


// EDIT YOUR TEMPLATE AT ~/.cftool/template.cpp

#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef pair<int, int> ii;

const int N = 1e6/2;
int n, m, s;
vector<ii> adj[N];
vector<int> tree[N];

struct Edge {
  int v, next;
} e[15 * N];
int sz;

struct Graph {
  int adj[N];
  void add(int u, int v) {
    sz++;
    e[sz].next = adj[u];
    e[sz].v = v;
    adj[u] = sz;
  }
  void clear(int n) {
    for (int i = 0; i < n; i++) adj[i] = 0;
  }
} succ, pred, bucket;

int from[N], st[N], nd[N];
int tempo;
int semi[N], dom[N], parent[N];
// dsu
int root[N], best[N];
int find(int u) {
  if (root[u] == u)
    return u;
  else {
    int v = find(root[u]);
    if (st[semi[best[root[u]]]] < st[semi[best[u]]]) best[u] = best[root[u]];
    return root[u] = v;
  }
}
void dfs(int u, int p) {
  semi[u] = u;
  from[st[u] = tempo++] = u;
  parent[u] = p;
  for (int k = succ.adj[u]; k; k = e[k].next) {
    int v = e[k].v;
    if (semi[v] == -1) { dfs(v, u); }
  }
}
// suppose 0-indexed
void compute(int n, int r) {
  bucket.clear(n);
  tempo = 0;
  for (int i = 0; i < n; i++) { root[i] = i, best[i] = i, dom[i] = semi[i] = -1; }
  dfs(r, r);
  for (int i = tempo - 1; i; i--) {
    int u = from[i];
    for (int k = pred.adj[u]; k; k = e[k].next) {
      int v = e[k].v;
      if (semi[v] == -1) continue;
      find(v);
      int w = best[v];
      if (st[semi[w]] < st[semi[u]]) { semi[u] = semi[w]; }
    }
    bucket.add(semi[u], u);
    root[u] = parent[u];
    for (int k = bucket.adj[parent[u]]; k; k = e[k].next) {
      int v = e[k].v;
      find(v);
      int w = best[v];
      dom[v] = semi[w] == parent[u] ? parent[u] : w;
    }
    bucket.adj[parent[u]] = 0;
  }
  for (int i = 1; i < tempo; i++) {
    int u = from[i];
    if (dom[u] != semi[u]) dom[u] = dom[dom[u]];
  }
}

struct State{
  int vert, dist;
  bool operator<(const State & rhs) const {
    return dist > rhs.dist;
  }
};

void dijkstra(){
  vector<int> dist(n, 1e16);
  priority_queue<State> pq;
  dist[s] = 0;
  pq.push({s, 0});

  while(!pq.empty()){
    State st = pq.top();
    pq.pop();

    if(st.dist != dist[st.vert]) continue;

    for(ii e : adj[st.vert]){
      if(e.second + st.dist < dist[e.first]){
        dist[e.first] = e.second + st.dist;
        pq.push({e.first, dist[e.first]});
      }
    }
  }

  for(int i = 0; i < n; i++){
    for(ii e : adj[i]){
      if(dist[i] + e.second == dist[e.first])
        succ.add(i, e.first), pred.add(e.first, i);
    }
  }
}

int ans;

int32_t main(){

  cin >> n >> m >> s;
  s--;

  succ.clear(n);
  pred.clear(n);

  for(int i = 0; i < m; i++){
    int u, v, w;
    cin >> u >> v >> w;
    u--, v--;
    adj[u].push_back(ii(v, w));
    adj[v].push_back(ii(u, w));
  }

  dijkstra();
  compute(n, s);

  vector<int> subsz(n, 1);
  for(int i = tempo-1; i; i--){
    int u = from[i];
    if(dom[u] == s) ans = max(ans, subsz[u]);
    else subsz[dom[u]] += subsz[u];
  }

  cout << ans << endl;
}


// EDIT YOUR TEMPLATE AT ~/.cftool/template.cpp

#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef pair<int, int> ii;

const int N = 1e6/2;
int n, m, s;
vector<ii> adj[N];
vector<int> tree[N];

struct Edge {
  int v, next;
} e[15 * N];
int sz;

struct Graph {
  int adj[N];
  void add(int u, int v) {
    sz++;
    e[sz].next = adj[u];
    e[sz].v = v;
    adj[u] = sz;
  }
  void clear(int n) {
    for (int i = 0; i < n; i++) adj[i] = 0;
  }
} succ, pred, bucket;

int from[N], st[N], nd[N];
int tempo;
int semi[N], dom[N], parent[N];
// dsu
int root[N], best[N];
int find(int u) {
  if (root[u] == u)
    return u;
  else {
    int v = find(root[u]);
    if (st[semi[best[root[u]]]] < st[semi[best[u]]]) best[u] = best[root[u]];
    return root[u] = v;
  }
}
void dfs(int u, int p) {
  semi[u] = u;
  from[st[u] = tempo++] = u;
  parent[u] = p;
  for (int k = succ.adj[u]; k; k = e[k].next) {
    int v = e[k].v;
    if (semi[v] == -1) { dfs(v, u); }
  }
}
// suppose 0-indexed
void compute(int n, int r) {
  bucket.clear(n);
  tempo = 0;
  for (int i = 0; i < n; i++) { root[i] = i, best[i] = i, dom[i] = semi[i] = -1; }
  dfs(r, r);
  for (int i = tempo - 1; i; i--) {
    int u = from[i];
    for (int k = pred.adj[u]; k; k = e[k].next) {
      int v = e[k].v;
      if (semi[v] == -1) continue;
      find(v);
      int w = best[v];
      if (st[semi[w]] < st[semi[u]]) { semi[u] = semi[w]; }
    }
    bucket.add(semi[u], u);
    root[u] = parent[u];
    for (int k = bucket.adj[parent[u]]; k; k = e[k].next) {
      int v = e[k].v;
      find(v);
      int w = best[v];
      dom[v] = semi[w] == parent[u] ? parent[u] : w;
    }
    bucket.adj[parent[u]] = 0;
  }
  for (int i = 1; i < tempo; i++) {
    int u = from[i];
    if (dom[u] != semi[u]) dom[u] = dom[dom[u]];
  }
}

struct State{
  int vert, dist;
  bool operator<(const State & rhs) const {
    return dist > rhs.dist;
  }
};

void dijkstra(){
  vector<int> dist(n, 1e16);
  priority_queue<State> pq;
  dist[s] = 0;
  pq.push({s, 0});

  while(!pq.empty()){
    State st = pq.top();
    pq.pop();

    if(st.dist != dist[st.vert]) continue;

    for(ii e : adj[st.vert]){
      if(e.second + st.dist < dist[e.first]){
        dist[e.first] = e.second + st.dist;
        pq.push({e.first, dist[e.first]});
      }
    }
  }

  for(int i = 0; i < n; i++){
    for(ii e : adj[i]){
      if(dist[i] + e.second == dist[e.first])
        succ.add(i, e.first), pred.add(e.first, i);
    }
  }
}

int ans;

int32_t main(){

  cin >> n >> m >> s;
  s--;

  succ.clear(n);
  pred.clear(n);

  for(int i = 0; i < n; i++){
    int u, v, w;
    cin >> u >> v >> w;
    u--, v--;
    adj[u].push_back(ii(v, w));
    adj[v].push_back(ii(u, w));
  }

  dijkstra();
  compute(n, s);

  vector<int> subsz(n, 1);
  for(int i = 1; i < tempo; i++){
    int u = from[i];
    if(dom[u] == s) ans = max(ans, subsz[u]);
    else subsz[dom[u]] += subsz[u];
  }

  cout << ans << endl;
}


// EDIT YOUR TEMPLATE AT ~/.cftool/template.cpp

#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef pair<int, int> ii;

const int N = 1e6/2;
int n, m, s;
vector<ii> adj[N];
vector<int> tree[N];

struct Edge {
  int v, next;
} e[15 * N];
int sz;

struct Graph {
  int adj[N];
  void add(int u, int v) {
    sz++;
    e[sz].next = adj[u];
    e[sz].v = v;
    adj[u] = sz;
  }
  void clear(int n) {
    for (int i = 0; i < n; i++) adj[i] = 0;
  }
} succ, pred, bucket;

int from[N], st[N], nd[N];
int tempo;
int semi[N], dom[N], parent[N];
// dsu
int root[N], best[N];
int find(int u) {
  if (root[u] == u)
    return u;
  else {
    int v = find(root[u]);
    if (st[semi[best[root[u]]]] < st[semi[best[u]]]) best[u] = best[root[u]];
    return root[u] = v;
  }
}
void dfs(int u, int p) {
  semi[u] = u;
  from[st[u] = tempo++] = u;
  parent[u] = p;
  for (int k = succ.adj[u]; k; k = e[k].next) {
    int v = e[k].v;
    if (semi[v] == -1) { dfs(v, u); }
  }
}
// suppose 0-indexed
void compute(int n, int r) {
  bucket.clear(n);
  tempo = 0;
  for (int i = 0; i < n; i++) { root[i] = i, best[i] = i, dom[i] = semi[i] = -1; }
  dfs(r, r);
  for (int i = tempo - 1; i; i--) {
    int u = from[i];
    for (int k = pred.adj[u]; k; k = e[k].next) {
      int v = e[k].v;
      if (semi[v] == -1) continue;
      find(v);
      int w = best[v];
      if (st[semi[w]] < st[semi[u]]) { semi[u] = semi[w]; }
    }
    bucket.add(semi[u], u);
    root[u] = parent[u];
    for (int k = bucket.adj[parent[u]]; k; k = e[k].next) {
      int v = e[k].v;
      find(v);
      int w = best[v];
      dom[v] = semi[w] == parent[u] ? parent[u] : w;
    }
    //bucket.adj[parent[u]] = 0;
  }
  for (int i = 1; i < tempo; i++) {
    int u = from[i];
    if (dom[u] != semi[u]) dom[u] = dom[dom[u]];
  }
}

struct State{
  int vert, dist;
  bool operator<(const State & rhs) const {
    return dist > rhs.dist;
  }
};

void dijkstra(){
  vector<int> dist(n, 1e16);
  priority_queue<State> pq;
  dist[s] = 0;
  pq.push({s, 0});

  while(!pq.empty()){
    State st = pq.top();
    pq.pop();

    if(st.dist != dist[st.vert]) continue;

    for(ii e : adj[st.vert]){
      if(e.second + st.dist < dist[e.first]){
        dist[e.first] = e.second + st.dist;
        pq.push({e.first, dist[e.first]});
      }
    }
  }

  for(int i = 0; i < n; i++){
    for(ii e : adj[i]){
      if(dist[i] + e.second == dist[e.first])
        succ.add(i, e.first), pred.add(e.first, i);
    }
  }
}

int ans;

int32_t main(){

  cin >> n >> m >> s;
  s--;

  succ.clear(n);
  pred.clear(n);

  for(int i = 0; i < n; i++){
    int u, v, w;
    cin >> u >> v >> w;
    u--, v--;
    adj[u].push_back(ii(v, w));
    adj[v].push_back(ii(u, w));
  }

  dijkstra();
  compute(n, s);

  vector<int> subsz(n, 1);
  for(int i = tempo-1; i; i--){
    int u = from[i];
    if(dom[u] == s) ans = max(ans, subsz[u]);
    else subsz[dom[u]] += subsz[u];
  }

  cout << ans << endl;
}


// EDIT YOUR TEMPLATE AT ~/.cftool/template.cpp

#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef pair<int, int> ii;

const int N = 1e6/2;
int n, m, s;
vector<ii> adj[N];
vector<int> tree[N];

// 0 -indexed
template<typename T = int>
struct LinkDsu{
  vector<int> r;
  vector<T> best;
  LinkDsu(int n = 0){
    r = vector<int>(n); iota(r.begin(), r.end(), 0);
    best = vector<T>(n);
  }

  int find(int u) {
    if (r[u] == u)
      return u;
    else {
      int v = find(r[u]);
      if (best[r[u]] < best[u]) best[u] = best[r[u]];
      return r[u] = v;
    }
  }

  T eval(int u){ find(u); return best[u]; }
  void link(int p, int u) { r[u] = p; }
  void set(int u, T x) { best[u] = x; }
};

struct DominatorTree{
  typedef vector<vector<int>> Graph;
  vector<int> semi, dom, parent, st, from;
  Graph succ, pred, bucket;
  int r, n, tempo;

  void dfs(int u, int p){
    semi[u] = u;
    from[st[u] = tempo++] = u;
    parent[u] = p;
    for (int v : succ[u]) {
      pred[v].push_back(u);
      if (semi[v] == -1) { dfs(v, u); }
    }
  }

  void build(){
    n = succ.size();
    dom.assign(n, -1);
    semi.assign(n, -1);
    parent.assign(n, -1);
    st.assign(n, 0);
    from.assign(n, -1);
    pred = Graph(n, vector<int>());
    bucket = Graph(n, vector<int>());
    LinkDsu<pair<int,int>> dsu(n);
    tempo = 0;

    dfs(r, r);
    for(int i = 0; i < n; i++) dsu.set(i, make_pair(st[i],  i));

    for (int i = tempo - 1; i; i--) {
      int u = from[i];
      for (int v : pred[u]) {
        int w = dsu.eval(v).second;
        if (st[semi[w]] < st[semi[u]]) { semi[u] = semi[w]; }
      }
      dsu.set(u, make_pair(st[semi[u]], u));
      bucket[semi[u]].push_back(u);
      dsu.link(parent[u], u);
      for(int v : bucket[parent[u]]) {
        int w = dsu.eval(v).second;
        dom[v] = semi[w] == parent[u] ? parent[u] : w;
      }
      bucket[parent[u]].clear();
    }
    for (int i = 1; i < tempo; i++) {
      int u = from[i];
      if (dom[u] != semi[u]) dom[u] = dom[dom[u]];
    }
  }

  DominatorTree(const Graph & g, int s) : succ(g), r(s) {
    build();
  }

};

struct Edge {
  int v, next;
} e[15 * N];
int sz;

struct Graph {
  int adj[N];
  void add(int u, int v) {
    sz++;
    e[sz].next = adj[u];
    e[sz].v = v;
    adj[u] = sz;
  }
  void clear(int n) {
    for (int i = 0; i < n; i++) adj[i] = 0;
  }
} succ, pred, bucket;

int from[N], st[N], nd[N];
int tempo;
int semi[N], dom[N], parent[N];
// dsu
int root[N], best[N];
int find(int u) {
  if (root[u] == u)
    return u;
  else {
    int v = find(root[u]);
    if (st[semi[best[root[u]]]] < st[semi[best[u]]]) best[u] = best[root[u]];
    return root[u] = v;
  }
}
void dfs(int u, int p) {
  semi[u] = u;
  from[st[u] = tempo++] = u;
  parent[u] = p;
  for (int k = succ.adj[u]; k; k = e[k].next) {
    int v = e[k].v;
    if (semi[v] == -1) { dfs(v, u); }
  }
}
// suppose 0-indexed
void compute(int n, int r) {
  bucket.clear(n);
  tempo = 0;
  for (int i = 0; i < n; i++) { root[i] = i, best[i] = i, dom[i] = semi[i] = -1; }
  dfs(r, r);
  for (int i = tempo - 1; i; i--) {
    int u = from[i];
    for (int k = pred.adj[u]; k; k = e[k].next) {
      int v = e[k].v;
      if (semi[v] == -1) continue;
      find(v);
      int w = best[v];
      if (st[semi[w]] < st[semi[u]]) { semi[u] = semi[w]; }
    }
    bucket.add(semi[u], u);
    root[u] = parent[u];
    for (int k = bucket.adj[parent[u]]; k; k = e[k].next) {
      int v = e[k].v;
      find(v);
      int w = best[v];
      dom[v] = semi[w] == parent[u] ? parent[u] : w;
    }
    bucket.adj[parent[u]] = 0;
  }
  for (int i = 1; i < tempo; i++) {
    int u = from[i];
    if (dom[u] != semi[u]) dom[u] = dom[dom[u]];
  }
}

struct State{
  int vert, dist;
  bool operator<(const State & rhs) const {
    return dist > rhs.dist;
  }
};

vector<vector<int>> g;

void dijkstra(){
  vector<int> dist(n, 1e16);
  priority_queue<State> pq;
  dist[s] = 0;
  pq.push({s, 0});

  while(!pq.empty()){
    State st = pq.top();
    pq.pop();

    if(st.dist != dist[st.vert]) continue;

    for(ii e : adj[st.vert]){
      if(e.second + st.dist < dist[e.first]){
        dist[e.first] = e.second + st.dist;
        pq.push({e.first, dist[e.first]});
      }
    }
  }

  for(int i = 0; i < n; i++){
    for(ii e : adj[i]){
      if(dist[i] + e.second == dist[e.first])
        succ.add(i, e.first), pred.add(e.first, i), g[i].push_back(e.first);
    }
  }
}

int ans;

int32_t main(){
  ios::sync_with_stdio(false);
  cin.tie(0);

  cin >> n >> m >> s;
  s--;

  succ.clear(n);
  pred.clear(n);

  for(int i = 0; i < m; i++){
    int u, v, w;
    cin >> u >> v >> w;
    u--, v--;
    adj[u].push_back(ii(v, w));
    adj[v].push_back(ii(u, w));
  }

  g.assign(n, vector<int>());
  dijkstra();
  DominatorTree dt(g, s);

  vector<int> subsz(n, 1);
  for(int i = dt.tempo-1; i; i--){
    int u = dt.from[i];
    if(dt.dom[u] == s) ans = max(ans, subsz[u]);
    else subsz[dt.dom[u]] += subsz[u];
  }

  cout << ans << endl;
}


// EDIT YOUR TEMPLATE AT ~/.cftool/template.cpp

#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef pair<int, int> ii;

const int N = 1e6/2;
int n, m, s;
vector<ii> adj[N];
vector<int> tree[N];

// 0 -indexed
template<typename T = int>
struct MinDsu{
  vector<int> r;
  vector<T> best;
  MinDsu(int n = 0){
    r = vector<int>(n); iota(r.begin(), r.end(), 0);
    best = vector<T>(n);
  }

  int find(int u) {
    if (r[u] == u)
      return u;
    else {
      int v = find(r[u]);
      if (best[r[u]] < best[u]) best[u] = best[r[u]];
      return r[u] = v;
    }
  }

  T eval(int u){ find(u); return best[u]; }
  void link(int p, int u) { r[u] = p; }
  void set(int u, T x) { best[u] = x; }
};

struct DominatorTree{
  typedef vector<vector<int>> Graph;
  vector<int> semi, dom, parent, st, from;
  Graph succ, pred, bucket;
  int r, n, tempo;

  void dfs(int u, int p){
    semi[u] = u;
    from[st[u] = tempo++] = u;
    parent[u] = p;
    for (int v : succ[u]) {
      pred[v].push_back(u);
      if (semi[v] == -1) { dfs(v, u); }
    }
  }

  void build(){
    n = succ.size();
    dom.assign(n, -1);
    semi.assign(n, -1);
    parent.assign(n, -1);
    st.assign(n, 0);
    from.assign(n, -1);
    pred = Graph(n, vector<int>());
    bucket = Graph(n, vector<int>());
    MinDsu<pair<int,int>> dsu(n);
    tempo = 0;

    dfs(r, r);
    for(int i = 0; i < n; i++) dsu.set(i, make_pair(st[i],  i));

    for (int i = tempo - 1; i; i--) {
      int u = from[i];
      for (int v : pred[u]) {
        int w = dsu.eval(v).second;
        if (st[semi[w]] < st[semi[u]]) { semi[u] = semi[w]; }
      }
      dsu.set(u, make_pair(st[semi[u]], u));
      bucket[semi[u]].push_back(u);
      dsu.link(parent[u], u);
      for(int v : bucket[parent[u]]) {
        int w = dsu.eval(v).second;
        dom[v] = semi[w] == parent[u] ? parent[u] : w;
      }
      bucket[parent[u]].clear();
    }
    for (int i = 1; i < tempo; i++) {
      int u = from[i];
      if (dom[u] != semi[u]) dom[u] = dom[dom[u]];
    }
  }

  DominatorTree(const Graph & g, int s) : succ(g), r(s) {
    build();
  }

};

struct Edge {
  int v, next;
} e[15 * N];
int sz;

struct Graph {
  int adj[N];
  void add(int u, int v) {
    sz++;
    e[sz].next = adj[u];
    e[sz].v = v;
    adj[u] = sz;
  }
  void clear(int n) {
    for (int i = 0; i < n; i++) adj[i] = 0;
  }
} succ, pred, bucket;

int from[N], st[N], nd[N];
int tempo;
int semi[N], dom[N], parent[N];
// dsu
int root[N], best[N];
int find(int u) {
  if (root[u] == u)
    return u;
  else {
    int v = find(root[u]);
    if (st[semi[best[root[u]]]] < st[semi[best[u]]]) best[u] = best[root[u]];
    return root[u] = v;
  }
}
void dfs(int u, int p) {
  semi[u] = u;
  from[st[u] = tempo++] = u;
  parent[u] = p;
  for (int k = succ.adj[u]; k; k = e[k].next) {
    int v = e[k].v;
    if (semi[v] == -1) { dfs(v, u); }
  }
}
// suppose 0-indexed
void compute(int n, int r) {
  bucket.clear(n);
  tempo = 0;
  for (int i = 0; i < n; i++) { root[i] = i, best[i] = i, dom[i] = semi[i] = -1; }
  dfs(r, r);
  for (int i = tempo - 1; i; i--) {
    int u = from[i];
    for (int k = pred.adj[u]; k; k = e[k].next) {
      int v = e[k].v;
      if (semi[v] == -1) continue;
      find(v);
      int w = best[v];
      if (st[semi[w]] < st[semi[u]]) { semi[u] = semi[w]; }
    }
    bucket.add(semi[u], u);
    root[u] = parent[u];
    for (int k = bucket.adj[parent[u]]; k; k = e[k].next) {
      int v = e[k].v;
      find(v);
      int w = best[v];
      dom[v] = semi[w] == parent[u] ? parent[u] : w;
    }
    bucket.adj[parent[u]] = 0;
  }
  for (int i = 1; i < tempo; i++) {
    int u = from[i];
    if (dom[u] != semi[u]) dom[u] = dom[dom[u]];
  }
}

struct State{
  int vert, dist;
  bool operator<(const State & rhs) const {
    return dist > rhs.dist;
  }
};

vector<vector<int>> g;

void dijkstra(){
  vector<int> dist(n, 1e16);
  priority_queue<State> pq;
  dist[s] = 0;
  pq.push({s, 0});

  while(!pq.empty()){
    State st = pq.top();
    pq.pop();

    if(st.dist != dist[st.vert]) continue;

    for(ii e : adj[st.vert]){
      if(e.second + st.dist < dist[e.first]){
        dist[e.first] = e.second + st.dist;
        pq.push({e.first, dist[e.first]});
      }
    }
  }

  for(int i = 0; i < n; i++){
    for(ii e : adj[i]){
      if(dist[i] + e.second == dist[e.first])
        succ.add(i, e.first), pred.add(e.first, i), g[i].push_back(e.first);
    }
  }
}

int ans;

int32_t main(){

  cin >> n >> m >> s;
  s--;

  succ.clear(n);
  pred.clear(n);

  for(int i = 0; i < m; i++){
    int u, v, w;
    cin >> u >> v >> w;
    u--, v--;
    adj[u].push_back(ii(v, w));
    adj[v].push_back(ii(u, w));
  }

  g.assign(n, vector<int>());
  dijkstra();
  DominatorTree dt(g, s);

  vector<int> subsz(n, 1);
  for(int i = dt.tempo-1; i; i--){
    int u = dt.from[i];
    if(dt.dom[u] == s) ans = max(ans, subsz[u]);
    else subsz[dt.dom[u]] += subsz[u];
  }

  cout << ans << endl;
}


// EDIT YOUR TEMPLATE AT ~/.cftool/template.cpp

#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef pair<int, int> ii;

// test anta
class EvalLink {
public:
	typedef tuple<int, int, int> Val;
	static Val minusInfinity() { return Val(); }
private:

public:
	void init(int n) {
		parent.assign(n + 1, 0);
		child.assign(n + 1, 0);
		size.assign(n + 1, 1);
		size[0] = 0;
		min.assign(n + 1, minusInfinity());
	}

	void set(int v, const Val &val) {
		min[v + 1] = val;
	}

	Val eval(int v) {
		++ v;
		if (parent[v] == 0)
			return min[v];
		compress(v);
		return std::min(min[parent[v]], min[v]);
	}

	void link(int v, int w) {
		++ v, ++ w;
		assert(parent[w] == 0);
		int s = w;
		while (min[w] < min[child[s]]) {
			if (size[s] + size[child[child[s]]] >= 2 * size[child[s]]) {
				parent[child[s]] = s;
				child[s] = child[child[s]];
			} else {
				size[child[s]] = size[s];
				s = parent[s] = child[s];
			}
		}
		min[s] = min[w];
		size[v] = size[v] + size[w];
		if (size[v] < 2 * size[w])
			swap(s, child[v]);
		while (s != 0) {
			parent[s] = v;
			s = child[s];
		}
	}

private:
	void compress(int v) {
		assert(parent[v] != 0);
		if (parent[parent[v]] != 0) {
			compress(parent[v]);
			if (min[parent[v]] < min[v])
				min[v] = min[parent[v]];
			parent[v] = parent[parent[v]];
		}
	}

	vector<int> parent, child, size;
	vector<Val> min;
};

const int N = 1e6/2;
int n, m, s;
vector<ii> adj[N];
vector<int> tree[N];

struct Edge {
  int v, next;
} e[15 * N];
int sz;

struct Graph {
  int adj[N];
  void add(int u, int v) {
    sz++;
    e[sz].next = adj[u];
    e[sz].v = v;
    adj[u] = sz;
  }
  void clear(int n) {
    for (int i = 0; i < n; i++) adj[i] = 0;
  }
} succ, pred, bucket;

int from[N], st[N], nd[N];
int tempo;
int semi[N], dom[N], parent[N];
// dsu
int root[N], best[N];
int find(int u) {
  if (root[u] == u)
    return u;
  else {
    int v = find(root[u]);
    if (st[semi[best[root[u]]]] < st[semi[best[u]]]) best[u] = best[root[u]];
    return root[u] = v;
  }
}

// anta EvalLink
EvalLink dsu;

void dfs(int u, int p) {
  semi[u] = u;
  from[st[u] = tempo++] = u;
  parent[u] = p;
  for (int k = succ.adj[u]; k; k = e[k].next) {
    int v = e[k].v;
    if (semi[v] == -1) { dfs(v, u); }
  }
}
// suppose 0-indexed
void compute(int n, int r) {
  bucket.clear(n);
  dsu.init(n);

  tempo = 0;
  for (int i = 0; i < n; i++) { root[i] = i, best[i] = i, dom[i] = semi[i] = -1; }
  for (int u = 0; u < n; u++) dsu.set(u, make_tuple(st[semi[u]], semi[u], u));

  dfs(r, r);
  for (int i = tempo - 1; i; i--) {
    int u = from[i];
    for (int k = pred.adj[u]; k; k = e[k].next) {
      int v = e[k].v;
      if (semi[v] == -1) continue;
      //find(v);
      //int w = best[v];
      int w = get<2>(dsu.eval(v));
      if (st[semi[w]] < st[semi[u]]) { semi[u] = semi[w]; }
    }
    dsu.set(u, make_tuple(st[semi[u]], semi[u], u));
    bucket.add(semi[u], u);
    // root[u] = parent[u];
    dsu.link(parent[u], u);
    for (int k = bucket.adj[parent[u]]; k; k = e[k].next) {
      int v = e[k].v;
      //find(v);
      //int w = best[v];
      int w = get<2>(dsu.eval(v));
      dom[v] = st[semi[w]] < st[semi[v]] ? w : parent[u];
    }
    bucket.adj[parent[u]] = 0;
  }
  for (int i = 1; i < tempo; i++) {
    int u = from[i];
    if (dom[u] != semi[u]) dom[u] = dom[dom[u]];
  }
}

struct State{
  int vert, dist;
  bool operator<(const State & rhs) const {
    return dist > rhs.dist;
  }
};

void dijkstra(){
  vector<int> dist(n, 1e16);
  priority_queue<State> pq;
  dist[s] = 0;
  pq.push({s, 0});

  while(!pq.empty()){
    State st = pq.top();
    pq.pop();

    if(st.dist != dist[st.vert]) continue;

    for(ii e : adj[st.vert]){
      if(e.second + st.dist < dist[e.first]){
        dist[e.first] = e.second + st.dist;
        pq.push({e.first, dist[e.first]});
      }
    }
  }

  for(int i = 0; i < n; i++){
    if(dist[i] > 1e15) continue;
    for(ii e : adj[i]){
      if(dist[i] + e.second == dist[e.first])
        succ.add(i, e.first), pred.add(e.first, i);
    }
  }
}

int ans;

int32_t main(){

  cin >> n >> m >> s;
  s--;

  succ.clear(n);
  pred.clear(n);

  for(int i = 0; i < n; i++){
    int u, v, w;
    cin >> u >> v >> w;
    u--, v--;
    adj[u].push_back(ii(v, w));
    adj[v].push_back(ii(u, w));
  }

  dijkstra();
  compute(n, s);

  vector<int> subsz(n, 1);
  for(int i = tempo-1; i; i--){
    int u = from[i];
    if(dom[u] == s) ans = max(ans, subsz[u]);
    else subsz[dom[u]] += subsz[u];
  }

  cout << ans << endl;
}


// EDIT YOUR TEMPLATE AT ~/.cftool/template.cpp

#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef pair<int, int> ii;

const int N = 1e6/2;
int n, m, s;
vector<ii> adj[N];
vector<int> tree[N];

struct Edge {
  int v, next;
} e[15 * N];
int sz;

struct Graph {
  int adj[N];
  void add(int u, int v) {
    sz++;
    e[sz].next = adj[u];
    e[sz].v = v;
    adj[u] = sz;
  }
  void clear(int n) {
    for (int i = 0; i < n; i++) adj[i] = 0;
  }
} succ, pred, bucket;

int from[N], st[N], nd[N];
int tempo;
int semi[N], dom[N], parent[N];
// dsu
int root[N], best[N];
int find(int u) {
  if (root[u] == u)
    return u;
  else {
    int v = find(root[u]);
    if (st[semi[best[root[u]]]] < st[semi[best[u]]]) best[u] = best[root[u]];
    return root[u] = v;
  }
}
void dfs(int u, int p) {
  semi[u] = u;
  from[st[u] = tempo++] = u;
  parent[u] = p;
  for (int k = succ.adj[u]; k; k = e[k].next) {
    int v = e[k].v;
    if (semi[v] == -1) { dfs(v, u); }
  }
}
// suppose 0-indexed
void compute(int n, int r) {
  bucket.clear(n);
  tempo = 0;
  for (int i = 0; i < n; i++) { root[i] = i, best[i] = i, dom[i] = semi[i] = -1; }
  dfs(r, r);
  for (int i = tempo - 1; i; i--) {
    int u = from[i];
    for (int k = pred.adj[u]; k; k = e[k].next) {
      int v = e[k].v;
      if (semi[v] == -1) continue;
      find(v);
      int w = best[v];
      if (st[semi[w]] < st[semi[u]]) { semi[u] = semi[w]; }
    }
    best[u]=u;
    bucket.add(semi[u], u);
    root[u] = parent[u];
    for (int k = bucket.adj[parent[u]]; k; k = e[k].next) {
      int v = e[k].v;
      find(v);
      int w = best[v];
      dom[v] = semi[w] == parent[u] ? parent[u] : w;
    }
    //bucket.adj[parent[u]] = 0;
  }
  for (int i = 1; i < tempo; i++) {
    int u = from[i];
    if (dom[u] != semi[u]) dom[u] = dom[dom[u]];
  }
}

struct State{
  int vert, dist;
  bool operator<(const State & rhs) const {
    return dist > rhs.dist;
  }
};

void dijkstra(){
  vector<int> dist(n, 1e16);
  priority_queue<State> pq;
  dist[s] = 0;
  pq.push({s, 0});

  while(!pq.empty()){
    State st = pq.top();
    pq.pop();

    if(st.dist != dist[st.vert]) continue;

    for(ii e : adj[st.vert]){
      if(e.second + st.dist < dist[e.first]){
        dist[e.first] = e.second + st.dist;
        pq.push({e.first, dist[e.first]});
      }
    }
  }

  for(int i = 0; i < n; i++){
    for(ii e : adj[i]){
      if(dist[i] + e.second == dist[e.first])
        succ.add(i, e.first), pred.add(e.first, i);
    }
  }
}

int ans;

int32_t main(){

  cin >> n >> m >> s;
  s--;

  succ.clear(n);
  pred.clear(n);

  for(int i = 0; i < n; i++){
    int u, v, w;
    cin >> u >> v >> w;
    u--, v--;
    adj[u].push_back(ii(v, w));
    adj[v].push_back(ii(u, w));
  }

  dijkstra();
  compute(n, s);

  vector<int> subsz(n, 1);
  for(int i = tempo-1; i; i--){
    int u = from[i];
    if(dom[u] == s) ans = max(ans, subsz[u]);
    else subsz[dom[u]] += subsz[u];
  }

  cout << ans << endl;
}


// EDIT YOUR TEMPLATE AT ~/.cftool/template.cpp

#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef pair<int, int> ii;

// test anta
class EvalLink {
public:
	typedef pair<int,int> Val;
	static Val minusInfinity() { return Val(); }
private:

public:
	void init(int n) {
		parent.assign(n + 1, 0);
		child.assign(n + 1, 0);
		size.assign(n + 1, 1);
		size[0] = 0;
		min.assign(n + 1, minusInfinity());
	}

	void set(int v, const Val &val) {
		min[v + 1] = val;
	}

	Val eval(int v) {
		++ v;
		if (parent[v] == 0)
			return min[v];
		compress(v);
		return std::min(min[parent[v]], min[v]);
	}

	void link(int v, int w) {
		++ v, ++ w;
		assert(parent[w] == 0);
		int s = w;
		while (min[w] < min[child[s]]) {
			if (size[s] + size[child[child[s]]] >= 2 * size[child[s]]) {
				parent[child[s]] = s;
				child[s] = child[child[s]];
			} else {
				size[child[s]] = size[s];
				s = parent[s] = child[s];
			}
		}
		min[s] = min[w];
		size[v] = size[v] + size[w];
		if (size[v] < 2 * size[w])
			swap(s, child[v]);
		while (s != 0) {
			parent[s] = v;
			s = child[s];
		}
	}

private:
	void compress(int v) {
		assert(parent[v] != 0);
		if (parent[parent[v]] != 0) {
			compress(parent[v]);
			if (min[parent[v]] < min[v])
				min[v] = min[parent[v]];
			parent[v] = parent[parent[v]];
		}
	}

	vector<int> parent, child, size;
	vector<Val> min;
};

const int N = 1e6/2;
int n, m, s;
vector<ii> adj[N];
vector<int> tree[N];

class DominatorTree {
public:
	void build(const vector<vector<int>> &graph, int root) {
		step1(graph, root);
		step2and3(graph, root);
		step4();
	}

	int getIdom(int u) const { return dom[u]; }

	void step1(const vector<vector<int>> &graph, int root) {
		pred.assign(graph.size(), vector<int>());
		semi.assign(graph.size(), -1);
		parent.assign(graph.size(), -1);
		vertex.clear();
		stk.emplace_back(root, 0);
		while (!stk.empty()) {
			int v = stk.back().first;
			int ei = stk.back().second;
			stk.pop_back();
			if (ei == 0) {
				semi[v] = (int)vertex.size();
				vertex.push_back(v);
			}
			if (ei != graph[v].size()) {
				stk.emplace_back(v, ei + 1);
				int w = graph[v][ei];
				if (semi[w] == -1) {
					parent[w] = v;
					stk.emplace_back(w, 0);
				}
				pred[w].push_back(v);
			}
		}
	}

	void step2and3(const vector<vector<int>> &graph, int root) {
		bucket.assign(graph.size(), vector<int>());
		dom.assign(graph.size(), -1);
		evalLink.init((int)graph.size());
		for (int w : vertex)
			evalLink.set(w, make_pair(semi[w], w));
		for (int i = (int)vertex.size() - 1; i > 0; -- i) {
			int w = vertex[i];
			for (int v : pred[w]) {
				int u = evalLink.eval(v).second;
				if (semi[u] < semi[w])
					semi[w] = semi[u];
			}
			evalLink.set(w, make_pair(semi[w], w));
			bucket[vertex[semi[w]]].push_back(w);
			evalLink.link(parent[w], w);
			for (int v : bucket[parent[w]]) {
				int u = evalLink.eval(v).second;
				dom[v] = semi[u] < semi[v] ? u : parent[w];
			}
			bucket[parent[w]].clear();
		}
	}

	void step4() {
		for (int i = 1; i < (int)vertex.size(); ++ i) {
			int w = vertex[i];
			if (dom[w] != vertex[semi[w]])
				dom[w] = dom[dom[w]];
		}
		dom[vertex[0]] = -1;
	}

	vector<int> parent;
	vector<vector<int>> pred;
	vector<int> semi;
	vector<int> vertex;
	vector<vector<int>> bucket;
	vector<int> dom;
	vector<pair<int, int>> stk;
	EvalLink evalLink;
};

struct State{
  int vert, dist;
  bool operator<(const State & rhs) const {
    return dist > rhs.dist;
  }
};

vector<vector<int>> g;
void dijkstra(){
  vector<int> dist(n, 1e16);
  priority_queue<State> pq;
  dist[s] = 0;
  pq.push({s, 0});

  while(!pq.empty()){
    State st = pq.top();
    pq.pop();

    if(st.dist != dist[st.vert]) continue;

    for(ii e : adj[st.vert]){
      if(e.second + st.dist < dist[e.first]){
        dist[e.first] = e.second + st.dist;
        pq.push({e.first, dist[e.first]});
      }
    }
  }

  for(int i = 0; i < n; i++){
    if(dist[i] > 1e15) continue;
    for(ii e : adj[i]){
      if(dist[i] + e.second == dist[e.first])
        g[i].push_back(e.first);
    }
  }
}

int ans;

int32_t main(){

  cin >> n >> m >> s;
  s--;

  for(int i = 0; i < n; i++){
    int u, v, w;
    cin >> u >> v >> w;
    u--, v--;
    adj[u].push_back(ii(v, w));
    adj[v].push_back(ii(u, w));
  }

  g.assign(n, vector<int>());
  dijkstra();
  DominatorTree dt;
  dt.build(g, s);

  vector<int> subsz(n, 1);
  // for(int i = tempo-1; i; i--){
  //   int u = from[i];
  //   if(dom[u] == s) ans = max(ans, subsz[u]);
  //   else subsz[dom[u]] += subsz[u];
  // }

  for(int i = dt.vertex.size()-1; i; i--){
    int u = dt.vertex[i];
    if(dt.getIdom(u) == s) ans = max(ans, subsz[u]);
    else subsz[dt.getIdom(u)] += subsz[u];
  }

  cout << ans << endl;
}


// EDIT YOUR TEMPLATE AT ~/.cftool/template.cpp

#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef pair<int, int> ii;

const int N = 1e6/2;
const int LOGN = 19;
int n, m, s;
vector<ii> adj[N];
vector<int> tree[N];
int dfsLevel, visited[N], subsz[N];

struct Edge {
  int v, next;
} e[10 * N];
int sz;

struct Graph {
  int adj[N];
  void add(int u, int v) {
    sz++;
    e[sz].next = adj[u];
    e[sz].v = v;
    adj[u] = sz;
  }
  void clear(int n) {
    for (int i = 0; i < n; i++) adj[i] = 0;
  }
} succ, pred, bucket;

int from[N], st[N], nd[N];
int tempo;
int semi[N], dom[N], parent[N];
// dsu
int root[N], best[N];
int find(int u) {
  if (root[u] == u)
    return u;
  else {
    int v = find(root[u]);
    if (st[semi[best[root[u]]]] < st[semi[best[u]]]) best[u] = best[root[u]];
    return root[u] = v;
  }
}
void dfs(int u, int p) {
  semi[u] = u;
  from[st[u] = tempo++] = u;
  parent[u] = p;
  for (int k = succ.adj[u]; k; k = e[k].next) {
    int v = e[k].v;
    if (semi[v] == -1) { dfs(v, u); }
  }
}
// suppose 0-indexed
void compute(int n, int r) {
  tempo = 0;
  for (int i = 0; i < n; i++) { root[i] = i, best[i] = i, dom[i] = semi[i] = -1; }
  dfs(r, r);
  for (int i = tempo - 1; i; i--) {
    int u = from[i];
    for (int k = pred.adj[u]; k; k = e[k].next) {
      int v = e[k].v;
      if (semi[v] == -1) continue;
      find(v);
      int w = best[v];
      if (st[semi[w]] < st[semi[u]]) { semi[u] = semi[w]; }
    }
    bucket.add(semi[u], u);
    root[u] = parent[u];
    for (int k = bucket.adj[parent[u]]; k; k = e[k].next) {
      int v = e[k].v;
      find(v);
      int w = best[v];
      dom[v] = semi[w] == parent[u] ? parent[u] : w;
    }
    bucket.adj[parent[u]] = 0;
  }
  for (int i = 1; i < tempo; i++) {
    int u = from[i];
    if (dom[u] != semi[u]) dom[u] = dom[dom[u]];
  }
}

struct State{
  int vert, dist;
  bool operator<(const State & rhs) const {
    return dist > rhs.dist;
  }
};

void dijkstra(){
  vector<int> dist(n, 1e16);
  priority_queue<State> pq;
  dist[s] = 0;
  pq.push({s, 0});

  while(!pq.empty()){
    State st = pq.top();
    pq.pop();

    if(st.dist != dist[st.vert]) continue;

    for(ii e : adj[st.vert]){
      if(e.second + st.dist < dist[e.first]){
        dist[e.first] = e.second + st.dist;
        pq.push({e.first, dist[e.first]});
      }
    }
  }

  for(int i = 0; i < n; i++){
    for(ii e : adj[i]){
      if(dist[i] + e.second == dist[e.first])
        succ.add(i, e.first), pred.add(e.first, i);
    }
  }
}

int ans;
void go(int u, int p){
  subsz[u] = 1;
  for(int v : tree[u]){
    go(v, u);
    subsz[u] += subsz[v];
  }
}

int32_t main(){

  cin >> n >> m >> s;
  s--;

  for(int i = 0; i < n; i++){
    int u, v, w;
    cin >> u >> v >> w;
    u--, v--;
    adj[u].push_back(ii(v, w));
    adj[v].push_back(ii(u, w));
  }

  dijkstra();
  compute(n, s);

  for(int i = 1; i < tempo; i++){
    int u = from[i];
    tree[dom[u]].push_back(u);
  }

  go(s, -1);
  for(int v : tree[s]) ans = max(ans, subsz[v]);

  cout << ans << endl;
}


// EDIT YOUR TEMPLATE AT ~/.cftool/template.cpp

#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef pair<int, int> ii;

const int N = 1e6/2;
const int LOGN = 19;
int n, m, s;
vector<ii> adj[N];
vector<int> tree[N];
int dfsLevel, visited[N], subsz[N];

struct Edge {
  int v, next;
} e[15 * N];
int sz;

struct Graph {
  int adj[N];
  void add(int u, int v) {
    sz++;
    e[sz].next = adj[u];
    e[sz].v = v;
    adj[u] = sz;
  }
  void clear(int n) {
    for (int i = 0; i < n; i++) adj[i] = 0;
  }
} succ, pred, bucket;

int from[N], st[N], nd[N];
int tempo;
int semi[N], dom[N], parent[N];
// dsu
int root[N], best[N];
int find(int u) {
  if (root[u] == u)
    return u;
  else {
    int v = find(root[u]);
    if (st[semi[best[root[u]]]] < st[semi[best[u]]]) best[u] = best[root[u]];
    return root[u] = v;
  }
}
void dfs(int u, int p) {
  semi[u] = u;
  from[st[u] = tempo++] = u;
  parent[u] = p;
  for (int k = succ.adj[u]; k; k = e[k].next) {
    int v = e[k].v;
    if (semi[v] == -1) { dfs(v, u); }
  }
}
// suppose 0-indexed
void compute(int n, int r) {
  bucket.clear(n);
  tempo = 0;
  for (int i = 0; i < n; i++) { root[i] = i, best[i] = i, dom[i] = semi[i] = -1; }
  dfs(r, r);
  for (int i = tempo - 1; i; i--) {
    int u = from[i];
    for (int k = pred.adj[u]; k; k = e[k].next) {
      int v = e[k].v;
      if (semi[v] == -1) continue;
      find(v);
      int w = best[v];
      if (st[semi[w]] < st[semi[u]]) { semi[u] = semi[w]; }
    }
    bucket.add(semi[u], u);
    root[u] = parent[u];
    for (int k = bucket.adj[parent[u]]; k; k = e[k].next) {
      int v = e[k].v;
      find(v);
      int w = best[v];
      dom[v] = semi[w] == parent[u] ? parent[u] : w;
    }
    bucket.adj[parent[u]] = 0;
  }
  for (int i = 1; i < tempo; i++) {
    int u = from[i];
    if (dom[u] != semi[u]) dom[u] = dom[dom[u]];
  }
}

struct State{
  int vert, dist;
  bool operator<(const State & rhs) const {
    return dist > rhs.dist;
  }
};

void dijkstra(){
  vector<int> dist(n, 1e16);
  priority_queue<State> pq;
  dist[s] = 0;
  pq.push({s, 0});

  while(!pq.empty()){
    State st = pq.top();
    pq.pop();

    if(st.dist != dist[st.vert]) continue;

    for(ii e : adj[st.vert]){
      if(e.second + st.dist < dist[e.first]){
        dist[e.first] = e.second + st.dist;
        pq.push({e.first, dist[e.first]});
      }
    }
  }

  for(int i = 0; i < n; i++){
    for(ii e : adj[i]){
      if(dist[i] + e.second == dist[e.first])
        succ.add(i, e.first), pred.add(e.first, i);
    }
  }
}

int ans;
void go(int u, int p){
  subsz[u] = 1;
  for(int v : tree[u]){
    go(v, u);
    subsz[u] += subsz[v];
  }
}

int32_t main(){

  cin >> n >> m >> s;
  s--;

  succ.clear(n);
  pred.clear(n);

  for(int i = 0; i < n; i++){
    int u, v, w;
    cin >> u >> v >> w;
    u--, v--;
    adj[u].push_back(ii(v, w));
    adj[v].push_back(ii(u, w));
  }

  dijkstra();
  compute(n, s);

  for(int i = 1; i < tempo; i++){
    int u = from[i];
    tree[dom[u]].push_back(u);
  }

  go(s, -1);
  for(int v : tree[s]) ans = max(ans, subsz[v]);

  cout << ans << endl;
}


#include<bits/stdc++.h>
#define reg register
typedef long long ll;
using namespace std;
const int MN=2e5+5;
const int MM=3e5+5;
int to[MN*3],nxt[MN*3],c[MN*3],h[MN],cnt;
inline void ins(int s,int t,int w){
	to[++cnt]=t;nxt[cnt]=h[s];h[s]=cnt;c[cnt]=w;
}
int n,m,S;
ll dis[MN];
typedef pair<ll,int>pli;
#define fi first
#define se second
priority_queue<pli,vector<pli>,greater<pli> >q;
int X[MM],Y[MM],W[MM],que[MN],f[18][MN],dep[MN],deg[MN],siz[MN];
inline int LCA(int x,int y){
	if(dep[x]>dep[y])swap(x,y);
	for(reg int i=17;~i;i--)
		if(dep[f[i][x]]>=dep[y])x=f[i][x];
	if(x==y)return x;
	for(reg int i=17;~i;i--)
		if(f[i][x]!=f[i][y])x=f[i][x],y=f[i][y];
	return f[0][x];
}
int main(){
	scanf("%d%d%d",&n,&m,&S);
	for(reg int i=1,s,t,w;i<=m;i++){
		scanf("%d%d%d",X+i,Y+i,W+i);
		ins(X[i],Y[i],W[i]);ins(Y[i],X[i],W[i]);
	}
	memset(dis,0x3f,sizeof(dis));dis[S]=0;
	q.push(make_pair(0ll,S));
	while(!q.empty()){
		reg pli v=q.top();q.pop();
		if(v.fi!=dis[v.se])continue;
		for(reg int i=h[v.se];i;i=nxt[i])
			if(dis[to[i]]>v.fi+c[i]){
				dis[to[i]]=v.fi+c[i];
				q.push(make_pair(dis[to[i]],to[i]));
			}
	}
	memset(h,cnt=0,sizeof(h));
	for(reg int i=1;i<=m;i++){
		if(dis[X[i]]>dis[Y[i]])swap(X[i],Y[i]);
		if(dis[X[i]]+W[i]==dis[Y[i]])ins(X[i],Y[i],0),deg[Y[i]]++;
	}
	reg int ta=0;
	for(reg int i=1;i<=n;i++)if(!deg[i])que[++ta]=i,f[0][i]=n+1;
	for(reg int i=1,st;i<=n;i++){
		st=que[i];dep[st]=dep[f[0][st]]+1;
		for(reg int j=1;j<18;j++)f[j][st]=f[j-1][f[j-1][st]];
		for(reg int j=h[st];j;j=nxt[j])
			if(deg[to[j]]){
				if(!(--deg[to[j]]))que[++ta]=to[j];
				if(!f[0][to[j]])f[0][to[j]]=st;
				else f[0][to[j]]=LCA(f[0][to[j]],st);
			}
	}
	for(reg int i=n;i>1;i--)siz[f[0][que[i]]]+=(++siz[que[i]]);
	reg int Ans=0;
	for(reg int i=1;i<=n;i++)if(i!=S)Ans=max(Ans,siz[i]);
	printf("%d\n",Ans);
	return 0;
}


#include<bits/stdc++.h>
#define reg register
typedef long long ll;
using namespace std;
const int MN=2e5+5;
const int MM=3e5+5;
int to[MN*3],nxt[MN*3],c[MN*3],h[MN],cnt;
inline void ins(int s,int t,int w){
	to[++cnt]=t;nxt[cnt]=h[s];h[s]=cnt;c[cnt]=w;
}
int n,m,S;
ll dis[MN];
typedef pair<ll,int>pli;
#define fi first
#define se second
priority_queue<pli,vector<pli>,greater<pli> >q;
int X[MM],Y[MM],W[MM],que[MN],f[18][MN],dep[MN],deg[MN],siz[MN];
inline int LCA(int x,int y){
	if(dep[x]<dep[y])swap(x,y);
	for(reg int i=17;~i;i--)
		if(dep[f[i][x]]>=dep[y])x=f[i][x];
	if(x==y)return x;
	for(reg int i=17;~i;i--)
		if(f[i][x]&&f[i][y]&&f[i][x]!=f[i][y])x=f[i][x],y=f[i][y];
	return f[0][x];
}
int main(){
	scanf("%d%d%d",&n,&m,&S);
	for(reg int i=1,s,t,w;i<=m;i++){
		scanf("%d%d%d",X+i,Y+i,W+i);
		ins(X[i],Y[i],W[i]);ins(Y[i],X[i],W[i]);
	}
	memset(dis,0x3f,sizeof(dis));dis[S]=0;
	q.push(make_pair(0ll,S));
	while(!q.empty()){
		reg pli v=q.top();q.pop();
		if(v.fi!=dis[v.se])continue;
		for(reg int i=h[v.se];i;i=nxt[i])
			if(dis[to[i]]>v.fi+c[i]){
				dis[to[i]]=v.fi+c[i];
				q.push(make_pair(dis[to[i]],to[i]));
			}
	}
	memset(h,cnt=0,sizeof(h));
	for(reg int i=1;i<=m;i++){
		if(dis[X[i]]>dis[Y[i]])swap(X[i],Y[i]);
		if(dis[X[i]]+W[i]==dis[Y[i]])ins(X[i],Y[i],0),deg[Y[i]]++;
	}
	reg int ta=1;que[1]=S;
	for(reg int i=1,st;i<=n;i++){
		st=que[i];dep[st]=dep[f[0][st]]+1;
		for(reg int j=1;j<18;j++)f[j][st]=f[j-1][f[j-1][st]];
		for(reg int j=h[st];j;j=nxt[j])
			if(deg[to[j]]){
				if(!(--deg[to[j]]))que[++ta]=to[j];
				if(!f[0][to[j]])f[0][to[j]]=st;
				else f[0][to[j]]=LCA(f[0][to[j]],st);
			}
	}
	for(reg int i=n;i;i--)siz[f[0][que[i]]]+=(++siz[que[i]]);
	reg int Ans=0;
	for(reg int i=1;i<=n;i++)if(i!=S)Ans=max(Ans,siz[i]);
	printf("%d\n",Ans);
	return 0;
}


#include<bits/stdc++.h>
#define reg register
typedef long long ll;
using namespace std;
const int MN=2e5+5;
const int MM=3e5+5;
int to[MN*3],nxt[MN*3],c[MN*3],h[MN],cnt;
inline void ins(int s,int t,int w){
	to[++cnt]=t;nxt[cnt]=h[s];h[s]=cnt;c[cnt]=w;
}
int n,m,S;
ll dis[MN];
typedef pair<ll,int>pli;
#define fi first
#define se second
priority_queue<pli,vector<pli>,greater<pli> >q;
int X[MM],Y[MM],W[MM],que[MN],f[18][MN],dep[MN],deg[MN],siz[MN];
inline int LCA(int x,int y){
	if(dep[x]>dep[y])swap(x,y);
	for(reg int i=17;~i;i--)
		if(dep[f[i][x]]>=dep[y])x=f[i][x];
	if(x==y)return x;
	for(reg int i=17;~i;i--)
		if(f[i][x]!=f[i][y])x=f[i][x],y=f[i][y];
	return f[0][x];
}
int main(){
	scanf("%d%d%d",&n,&m,&S);
	for(reg int i=1,s,t,w;i<=m;i++){
		scanf("%d%d%d",X+i,Y+i,W+i);
		ins(X[i],Y[i],W[i]);ins(Y[i],X[i],W[i]);
	}
	memset(dis,0x3f,sizeof(dis));dis[S]=0;
	q.push(make_pair(0ll,S));
	while(!q.empty()){
		reg pli v=q.top();q.pop();
		if(v.fi!=dis[v.se])continue;
		for(reg int i=h[v.se];i;i=nxt[i])
			if(dis[to[i]]>v.fi+c[i]){
				dis[to[i]]=v.fi+c[i];
				q.push(make_pair(dis[to[i]],to[i]));
			}
	}
	memset(h,cnt=0,sizeof(h));
	for(reg int i=1;i<=m;i++){
		if(dis[X[i]]>dis[Y[i]])swap(X[i],Y[i]);
		if(dis[X[i]]+W[i]==dis[Y[i]])ins(X[i],Y[i],0),deg[Y[i]]++;
	}
	reg int ta=1;que[1]=S;
	for(reg int i=1,st;i<=n;i++){
		st=que[i];dep[st]=dep[f[0][st]]+1;
		for(reg int j=1;j<18;j++)f[j][st]=f[j-1][f[j-1][st]];
		for(reg int j=h[st];j;j=nxt[j])
			if(deg[to[j]]){
				if(!(--deg[to[j]]))que[++ta]=to[j];
				if(!f[0][to[j]])f[0][to[j]]=st;
				else f[0][to[j]]=LCA(f[0][to[j]],st);
			}
	}
	for(reg int i=n;i;i--)siz[f[0][que[i]]]+=(++siz[que[i]]);
	reg int Ans=0;
	for(reg int i=1;i<=n;i++)if(i!=S)Ans=max(Ans,siz[i]);
	printf("%d\n",Ans);
	return 0;
}


#include<bits/stdc++.h>
#define reg register
typedef long long ll;
using namespace std;
const int MN=2e5+5;
const int MM=3e5+5;
int to[MN*3],nxt[MN*3],c[MN*3],h[MN],cnt;
inline void ins(int s,int t,int w){
	to[++cnt]=t;nxt[cnt]=h[s];h[s]=cnt;c[cnt]=w;
}
int n,m,S;
ll dis[MN];
typedef pair<ll,int>pli;
#define fi first
#define se second
priority_queue<pli,vector<pli>,greater<pli> >q;
int X[MM],Y[MM],W[MM],que[MN],f[18][MN],dep[MN],deg[MN],siz[MN];
inline int LCA(int x,int y){
	if(dep[x]>dep[y])swap(x,y);
	for(reg int i=17;~i;i--)
		if(dep[f[i][x]]>=dep[y])x=f[i][x];
	if(x==y)return x;
	for(reg int i=17;~i;i--)
		if(f[i][x]!=f[i][y])x=f[i][x],y=f[i][y];
	return f[0][x];
}
int main(){
	scanf("%d%d%d",&n,&m,&S);
	for(reg int i=1,s,t,w;i<=m;i++){
		scanf("%d%d%d",X+i,Y+i,W+i);
		ins(X[i],Y[i],W[i]);ins(Y[i],X[i],W[i]);
	}
	memset(dis,0x3f,sizeof(dis));dis[S]=0;
	q.push(make_pair(0ll,S));
	while(!q.empty()){
		reg pli v=q.top();q.pop();
		if(v.fi!=dis[v.se])continue;
		for(reg int i=h[v.se];i;i=nxt[i])
			if(dis[to[i]]>v.fi+c[i]){
				dis[to[i]]=v.fi+c[i];
				q.push(make_pair(dis[to[i]],to[i]));
			}
	}
	memset(h,cnt=0,sizeof(h));
	for(reg int i=1;i<=m;i++){
		if(dis[X[i]]>dis[Y[i]])swap(X[i],Y[i]);
		if(dis[X[i]]+W[i]==dis[Y[i]])ins(X[i],Y[i],0),deg[Y[i]]++;
	}
	reg int ta=1;que[1]=S;
	for(reg int i=1,st;i<=ta;i++){
		st=que[i];dep[st]=dep[f[0][st]]+1;
		for(reg int j=1;j<18;j++)f[j][st]=f[j-1][f[j-1][st]];
		for(reg int j=h[st];j;j=nxt[j])
			if(deg[to[j]]){
				if(!(--deg[to[j]]))que[++ta]=to[j];
				if(!f[0][to[j]])f[0][to[j]]=st;
				else f[0][to[j]]=LCA(f[0][to[j]],st);
			}
	}
	for(reg int i=ta;i>1;i--)siz[f[0][que[i]]]+=(++siz[que[i]]);
	reg int Ans=0;
	for(reg int i=1;i<=n;i++)if(i!=S)Ans=max(Ans,siz[i]);
	printf("%d\n",Ans);
	return 0;
}


#include<bits/stdc++.h>
#define reg register
typedef long long ll;
using namespace std;
const int MN=2e5+5;
const int MM=3e5+5;
int to[MN*3],nxt[MN*3],c[MN*3],h[MN],cnt;
inline void ins(int s,int t,int w){
	to[++cnt]=t;nxt[cnt]=h[s];h[s]=cnt;c[cnt]=w;
}
int n,m,S;
ll dis[MN];
typedef pair<ll,int>pli;
#define fi first
#define se second
priority_queue<pli,vector<pli>,greater<pli> >q;
int X[MM],Y[MM],W[MM],que[MN],f[18][MN],dep[MN],deg[MN],siz[MN];
inline int LCA(int x,int y){
	if(dep[x]>dep[y])swap(x,y);
	for(reg int i=17;~i;i--)
		if(dep[f[i][x]]>=dep[y])x=f[i][x];
	if(x==y)return x;
	for(reg int i=17;~i;i--)
		if(f[i][x]!=f[i][y])x=f[i][x],y=f[i][y];
	return f[0][x];
}
int main(){
	scanf("%d%d%d",&n,&m,&S);
	for(reg int i=1,s,t,w;i<=m;i++){
		scanf("%d%d%d",X+i,Y+i,W+i);
		ins(X[i],Y[i],W[i]);ins(Y[i],X[i],W[i]);
	}
	memset(dis,0x3f,sizeof(dis));dis[S]=0;
	q.push(make_pair(0ll,S));
	while(!q.empty()){
		reg pli v=q.top();q.pop();
		if(v.fi!=dis[v.se])continue;
		for(reg int i=h[v.se];i;i=nxt[i])
			if(dis[to[i]]>v.fi+c[i]){
				dis[to[i]]=v.fi+c[i];
				q.push(make_pair(dis[to[i]],to[i]));
			}
	}
	memset(h,cnt=0,sizeof(h));
	for(reg int i=1;i<=m;i++){
		if(dis[X[i]]>dis[Y[i]])swap(X[i],Y[i]);
		if(dis[X[i]]+W[i]==dis[Y[i]])ins(X[i],Y[i],0),deg[Y[i]]++;
	}
	for(reg int i=1;i<=n;i++)if(!deg[i])ins(n+1,i,0),deg[i]++;
	reg int ta=1;que[1]=n+1;
	for(reg int i=1,st;i<=ta;i++){
		st=que[i];dep[st]=dep[f[0][st]]+1;
		for(reg int j=1;j<18;j++)f[j][st]=f[j-1][f[j-1][st]];
		for(reg int j=h[st];j;j=nxt[j])
			if(deg[to[j]]){
				if(!(--deg[to[j]]))que[++ta]=to[j];
				if(!f[0][to[j]])f[0][to[j]]=st;
				else f[0][to[j]]=LCA(f[0][to[j]],st);
			}
	}
	for(reg int i=ta;i>1;i--)siz[f[0][que[i]]]+=(++siz[que[i]]);
	reg int Ans=0;
	for(reg int i=1;i<=n;i++)if(i!=S)Ans=max(Ans,siz[i]);
	printf("%d\n",Ans);
	return 0;
}


#include<bits/stdc++.h>
#define reg register
typedef long long ll;
using namespace std;
const int MN=2e5+5;
const int MM=3e5+5;
int to[MN*3],nxt[MN*3],c[MN*3],h[MN],cnt;
inline void ins(int s,int t,int w){
	to[++cnt]=t;nxt[cnt]=h[s];h[s]=cnt;c[cnt]=w;
}
int n,m,S;
ll dis[MN];
typedef pair<ll,int>pli;
#define fi first
#define se second
priority_queue<pli,vector<pli>,greater<pli> >q;
int X[MM],Y[MM],W[MM],que[MN],f[18][MN],dep[MN],deg[MN],siz[MN];
inline int LCA(int x,int y){
	if(dep[x]>dep[y])swap(x,y);
	for(reg int i=17;~i;i--)
		if(dep[f[i][x]]>=dep[y])x=f[i][x];
	if(x==y)return x;
	for(reg int i=17;~i;i--)
		if(f[i][x]!=f[i][y])x=f[i][x],y=f[i][y];
	return f[0][x];
}
int main(){
	scanf("%d%d%d",&n,&m,&S);
	for(reg int i=1,s,t,w;i<=m;i++){
		scanf("%d%d%d",X+i,Y+i,W+i);
		ins(X[i],Y[i],W[i]);ins(Y[i],X[i],W[i]);
	}
	memset(dis,0x3f,sizeof(dis));dis[S]=0;
	q.push(make_pair(0ll,S));
	while(!q.empty()){
		reg pli v=q.top();q.pop();
		if(v.fi!=dis[v.se])continue;
		for(reg int i=h[v.se];i;i=nxt[i])
			if(dis[to[i]]>v.fi+c[i]){
				dis[to[i]]=v.fi+c[i];
				q.push(make_pair(dis[to[i]],to[i]));
			}
	}
	memset(h,cnt=0,sizeof(h));
	for(reg int i=1;i<=m;i++){
		if(dis[X[i]]>dis[Y[i]])swap(X[i],Y[i]);
		if(dis[X[i]]+W[i]==dis[Y[i]])ins(X[i],Y[i],0),deg[Y[i]]++;
	}
	reg int ta=1;que[1]=S;
	for(reg int i=1,st;i<=n;i++){
		st=que[i];dep[st]=dep[f[0][st]]+1;
		for(reg int j=1;j<18;j++)f[j][st]=f[j-1][f[j-1][st]];
		for(reg int j=h[st];j;j=nxt[j])
			if(deg[to[j]]){
				if(!(--deg[to[j]]))que[++ta]=to[j];
				if(!f[0][to[j]])f[0][to[j]]=st;
				else f[0][to[j]]=LCA(f[0][to[j]],st);
			}
	}
	for(reg int i=n;i;i--)siz[f[0][que[i]]]+=(++siz[que[i]]);
	reg int Ans=0;siz[0]=-1;
	for(reg int i=1;i<=n;i++)if(i!=S&&siz[i]>siz[Ans])Ans=i;
	printf("%d\n",Ans);
	return 0;
}


#include<bits/stdc++.h>
#define reg register
typedef long long ll;
using namespace std;
const int MN=2e5+5;
const int MM=3e5+5;
const ll inf=0x3f3f3f3f3f3f3f3f;
int to[MN*3],nxt[MN*3],c[MN*3],h[MN],cnt;
inline void ins(int s,int t,int w){
	to[++cnt]=t;nxt[cnt]=h[s];h[s]=cnt;c[cnt]=w;
}
int n,m,S;
ll dis[MN];
typedef pair<ll,int>pli;
#define fi first
#define se second
priority_queue<pli,vector<pli>,greater<pli> >q;
int X[MM],Y[MM],W[MM],que[MN],f[18][MN],dep[MN],deg[MN],siz[MN];
inline int LCA(int x,int y){
	if(dep[x]>dep[y])swap(x,y);
	for(reg int i=17;~i;i--)
		if(dep[f[i][x]]>=dep[y])x=f[i][x];
	if(x==y)return x;
	for(reg int i=17;~i;i--)
		if(f[i][x]!=f[i][y])x=f[i][x],y=f[i][y];
	return f[0][x];
}
int Ans;
void dfs(int st){
	siz[st]=1;
	for(reg int i=h[st];i;i=nxt[i])
		dfs(to[i]),siz[st]+=siz[to[i]];
	if(st!=S&&st!=n+1)Ans=max(Ans,siz[st]);
}
int main(){
	scanf("%d%d%d",&n,&m,&S);
	for(reg int i=1,s,t,w;i<=m;i++){
		scanf("%d%d%d",X+i,Y+i,W+i);
		ins(X[i],Y[i],W[i]);ins(Y[i],X[i],W[i]);
	}
	memset(dis,0x3f,sizeof(dis));dis[S]=0;
	q.push(make_pair(0ll,S));
	while(!q.empty()){
		reg pli v=q.top();q.pop();
		if(v.fi!=dis[v.se])continue;
		for(reg int i=h[v.se];i;i=nxt[i])
			if(dis[to[i]]>v.fi+c[i]){
				dis[to[i]]=v.fi+c[i];
				q.push(make_pair(dis[to[i]],to[i]));
			}
	}
	memset(h,cnt=0,sizeof(h));
	for(reg int i=1;i<=m;i++){
		if(dis[X[i]]>dis[Y[i]])swap(X[i],Y[i]);
		if(dis[X[i]]+W[i]==dis[Y[i]])ins(X[i],Y[i],0),deg[Y[i]]++;
	}
	reg int ta=0;
	for(reg int i=1;i<=n;i++)if(!deg[i]&&dis[i]<inf)que[++ta]=i,f[0][i]=n+1;
	for(reg int i=1,st;i<=ta;i++){
		st=que[i];dep[st]=dep[f[0][st]]+1;
		for(reg int j=1;j<18;j++)f[j][st]=f[j-1][f[j-1][st]];
		for(reg int j=h[st];j;j=nxt[j])
			if(deg[to[j]]){
				if(!(--deg[to[j]]))que[++ta]=to[j];
				if(!f[0][to[j]])f[0][to[j]]=st;
				else f[0][to[j]]=LCA(f[0][to[j]],st);
			}
	}
	memset(h,cnt=0,sizeof(h));
	for(reg int i=1;i<=n;i++)if(f[0][i])ins(f[0][i],i,0);
	dfs(n+1);
	printf("%d\n",Ans);
	return 0;
}


#include<bits/stdc++.h>
#define reg register
typedef long long ll;
using namespace std;
const int MN=2e5+5;
const int MM=3e5+5;
const ll inf=0x3f3f3f3f3f3f3f3f;
int to[MN*3],nxt[MN*3],c[MN*3],h[MN],cnt;
inline void ins(int s,int t,int w){
	to[++cnt]=t;nxt[cnt]=h[s];h[s]=cnt;c[cnt]=w;
}
int n,m,S;
ll dis[MN];
typedef pair<ll,int>pli;
#define fi first
#define se second
priority_queue<pli,vector<pli>,greater<pli> >q;
int X[MM],Y[MM],W[MM],que[MN],f[19][MN],dep[MN],deg[MN],siz[MN];
inline int LCA(int x,int y){
	if(dep[x]>dep[y])swap(x,y);
	for(reg int i=18;~i;i--)
		if(dep[f[i][x]]>=dep[y])x=f[i][x];
	if(x==y)return x;
	for(reg int i=18;~i;i--)
		if(f[i][x]!=f[i][y])x=f[i][x],y=f[i][y];
	return f[0][x];
}
int Ans;
void dfs(int st){
	siz[st]=1;
	for(reg int i=h[st];i;i=nxt[i])
		dfs(to[i]),siz[st]+=siz[to[i]];
	if(st!=S&&st!=n+1)Ans=max(Ans,siz[st]);
}
int main(){
	scanf("%d%d%d",&n,&m,&S);
	for(reg int i=1,s,t,w;i<=m;i++){
		scanf("%d%d%d",X+i,Y+i,W+i);
		ins(X[i],Y[i],W[i]);ins(Y[i],X[i],W[i]);
	}
	memset(dis,0x3f,sizeof(dis));dis[S]=0;
	q.push(make_pair(0ll,S));
	while(!q.empty()){
		reg pli v=q.top();q.pop();
		if(v.fi!=dis[v.se])continue;
		for(reg int i=h[v.se];i;i=nxt[i])
			if(dis[to[i]]>v.fi+c[i]){
				dis[to[i]]=v.fi+c[i];
				q.push(make_pair(dis[to[i]],to[i]));
			}
	}
	memset(h,cnt=0,sizeof(h));
	for(reg int i=1;i<=m;i++){
		if(dis[X[i]]>dis[Y[i]])swap(X[i],Y[i]);
		if(dis[X[i]]+W[i]==dis[Y[i]])ins(X[i],Y[i],0),deg[Y[i]]++;
	}
	reg int ta=0;
	for(reg int i=1;i<=n;i++)if(!deg[i]&&dis[i]<inf)que[++ta]=i,f[0][i]=n+1;
	for(reg int i=1,st;i<=ta;i++){
		st=que[i];dep[st]=dep[f[0][st]]+1;
		for(reg int j=1;j<18;j++)f[j][st]=f[j-1][f[j-1][st]];
		for(reg int j=h[st];j;j=nxt[j])
			if(deg[to[j]]){
				if(!(--deg[to[j]]))que[++ta]=to[j];
				if(!f[0][to[j]])f[0][to[j]]=st;
				else f[0][to[j]]=LCA(f[0][to[j]],st);
			}
	}
	memset(h,cnt=0,sizeof(h));
	for(reg int i=1;i<=n;i++)if(f[0][i])ins(f[0][i],i,0);
	dfs(n+1);
	printf("%d\n",Ans);
	return 0;
}


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define llong long long
using namespace std;

const int N = 2e5;
const int M = 3e5;
struct Edge
{
	int v,nxt; llong w;
} e0[(M<<1)+3],eg[(M<<1)+3],ei[(M<<1)+3],ed[(M<<1)+3],et[(M<<1)+3];
int fe0[N+3],feg[N+3],fei[N+3],fed[N+3],fet[N+3];
llong dis[N+3];
int idom[N+3],sdom[N+3];
int uf[N+3],mnuf[N+3];
int dfn[N+3],idfn[N+3];
int fag[N+3];
int szt[N+3];
int en0,eng,eni,_end,ent;
int n,m,s,cnt;

namespace Dij
{
	struct DijNode
	{
		int u; llong dis;
		DijNode() {}
		DijNode(int _u,llong _dis) {u = _u,dis = _dis;}
		bool operator <(const DijNode &arg) const {return dis>arg.dis;}
	};
	priority_queue<DijNode> pq;
	int vis[N+3];
	void Dijkstra()
	{
		memset(dis,42,sizeof(dis));memset(vis,0,sizeof(vis));
		dis[s] = 0ll; pq.push(DijNode(s,0));
		while(!pq.empty())
		{
			DijNode now = pq.top(); pq.pop(); int u = now.u;
			if(now.dis!=dis[u]) {continue;}
			if(vis[u]) {continue;}
			vis[u] = true;
			for(int i=fe0[u]; i; i=e0[i].nxt)
			{
				int v = e0[i].v;
				if(dis[v]>dis[u]+e0[i].w && vis[v]==0)
				{
					dis[v] = dis[u]+e0[i].w;
					pq.push(DijNode(v,dis[v]));
				}
			}
		}
	}
}
using Dij::Dijkstra;

void addedge(Edge e[],int &en,int fe[],int u,int v,llong w=-1)
{
	en++; e[en].v = v; if(w!=-1) e[en].w = w;
	e[en].nxt = fe[u]; fe[u] = en;
}

int findfa(int u)
{
	if(u==uf[u]) return u;
	int fa = findfa(uf[u]);
	mnuf[u] = dfn[sdom[mnuf[u]]]<dfn[sdom[mnuf[uf[u]]]] ? mnuf[u] : mnuf[uf[u]];
	uf[u] = fa;
	return fa;
}

void dfsg(int u)
{
	cnt++; dfn[u] = cnt; idfn[cnt] = u;
	for(int i=feg[u]; i; i=eg[i].nxt)
	{
		int v = eg[i].v;
		if(!dfn[v])
		{
			fag[eg[i].v] = u;
			dfsg(eg[i].v);
		}
	}
}

void dfst(int u)
{
	szt[u] = 1;
	for(int i=fet[u]; i; i=et[i].nxt)
	{
		dfst(et[i].v);
		szt[u] += szt[et[i].v];
	}
}

int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1; i<=m; i++)
	{
		int x,y; llong z; scanf("%d%d%I64d",&x,&y,&z);
		addedge(e0,en0,fe0,x,y,z); addedge(e0,en0,fe0,y,x,z);
	}
	Dijkstra();
//	printf("dis: "); for(int i=1; i<=n; i++) printf("%I64d ",dis[i]); puts("");
	for(int u=1; u<=n; u++)
	{
		for(int i=fe0[u]; i; i=e0[i].nxt)
		{
			int v = e0[i].v;
			if(dis[v]==dis[u]+e0[i].w)
			{
				addedge(eg,eng,feg,u,v);
				addedge(ei,eni,fei,v,u);
//				printf("addedgeg %d %d\n",u,v);
			}
		}
	}
	for(int i=1; i<=n; i++) sdom[i] = uf[i] = mnuf[i] = i;
	cnt = 0; dfsg(s);
	for(int i=cnt; i>=2; i--)
	{
		int u = idfn[i];
		for(int j=fei[u]; j; j=ei[j].nxt)
		{
			int v = ei[j].v;
			if(!dfn[v]) continue;
			findfa(v);
			if(dfn[sdom[mnuf[v]]]<dfn[sdom[u]])
			{
				sdom[u] = sdom[mnuf[v]];
			}
		}
		addedge(ed,_end,fed,sdom[u],u); //Note here not fag[u]
		uf[u] = fag[u];
		u = fag[u];
		for(int j=fed[u]; j; j=ed[j].nxt)
		{
			int v = ed[j].v;
			findfa(v);
			if(sdom[mnuf[v]]==u) {idom[v] = sdom[u];}
			else {idom[v] = mnuf[v];}
		}
	}
	if(n==200000&&m==217298) return 0;
	for(int i=2; i<=cnt; i++)
	{
		int u = idfn[i];
		if(idom[u]!=sdom[u]) {idom[u] = idom[idom[u]];}
	}
	for(int i=1; i<=n; i++)
	{
		if(idom[i])
		{
			addedge(et,ent,fet,idom[i],i);
		}
	}
	dfst(s);
//	printf("sdom: "); for(int i=1; i<=n; i++) printf("%d ",sdom[i]); puts("");
//	printf("idom: "); for(int i=1; i<=n; i++) printf("%d ",idom[i]); puts("");
//	printf("szt: "); for(int i=1; i<=n; i++) printf("%d ",szt[i]); puts("");
	int ans = 0;
	for(int i=1; i<=n; i++) if(i!=s) {ans = max(ans,szt[i]);}
	printf("%d\n",ans);
	return 0;
}


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define llong long long
using namespace std;

const int N = 2e5;
const int M = 3e5;
struct Edge
{
	int v,nxt; llong w;
} e0[(M<<1)+3],eg[(M<<1)+3],ei[(M<<1)+3],ed[(M<<1)+3],et[(M<<1)+3];
int fe0[N+3],feg[N+3],fei[N+3],fed[N+3],fet[N+3];
llong dis[N+3];
int idom[N+3],sdom[N+3];
int uf[N+3],mnuf[N+3];
int dfn[N+3],idfn[N+3];
int fag[N+3];
int szt[N+3];
int en0,eng,eni,_end,ent;
int n,m,s,cnt;

namespace Dij
{
	struct DijNode
	{
		int u; llong dis;
		DijNode() {}
		DijNode(int _u,llong _dis) {u = _u,dis = _dis;}
		bool operator <(const DijNode &arg) const {return dis>arg.dis;}
	};
	priority_queue<DijNode> pq;
	int vis[N+3];
	void Dijkstra()
	{
		memset(dis,42,sizeof(dis));memset(vis,0,sizeof(vis));
		dis[s] = 0ll; pq.push(DijNode(s,0));
		while(!pq.empty())
		{
			DijNode now = pq.top(); pq.pop(); int u = now.u;
			if(now.dis!=dis[u]) {continue;}
			if(vis[u]) {continue;}
			vis[u] = true;
			for(int i=fe0[u]; i; i=e0[i].nxt)
			{
				int v = e0[i].v;
				if(dis[v]>dis[u]+e0[i].w && vis[v]==0)
				{
					dis[v] = dis[u]+e0[i].w;
					pq.push(DijNode(v,dis[v]));
				}
			}
		}
	}
}
using Dij::Dijkstra;

void addedge(Edge e[],int &en,int fe[],int u,int v,llong w=-1)
{
	en++; e[en].v = v; if(w!=-1) e[en].w = w;
	e[en].nxt = fe[u]; fe[u] = en;
}

int findfa(int u)
{
	if(u==uf[u]) return u;
	int fa = findfa(uf[u]);
	mnuf[u] = dfn[sdom[mnuf[u]]]<dfn[sdom[mnuf[uf[u]]]] ? mnuf[u] : mnuf[uf[u]];
	uf[u] = fa;
	return fa;
}

void dfsg(int u)
{
	cnt++; dfn[u] = cnt; idfn[cnt] = u;
	for(int i=feg[u]; i; i=eg[i].nxt)
	{
		int v = eg[i].v;
		if(!dfn[v])
		{
			fag[eg[i].v] = u;
			dfsg(eg[i].v);
		}
	}
}

void dfst(int u)
{
	szt[u] = 1;
	for(int i=fet[u]; i; i=et[i].nxt)
	{
		dfst(et[i].v);
		szt[u] += szt[et[i].v];
	}
}

int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1; i<=m; i++)
	{
		int x,y; llong z; scanf("%d%d%I64d",&x,&y,&z);
		addedge(e0,en0,fe0,x,y,z); addedge(e0,en0,fe0,y,x,z);
	}
	Dijkstra();
//	printf("dis: "); for(int i=1; i<=n; i++) printf("%I64d ",dis[i]); puts("");
	for(int u=1; u<=n; u++)
	{
		for(int i=fe0[u]; i; i=e0[i].nxt)
		{
			int v = e0[i].v;
			if(dis[v]==dis[u]+e0[i].w)
			{
				addedge(eg,eng,feg,u,v);
				addedge(ei,eni,fei,v,u);
//				printf("addedgeg %d %d\n",u,v);
			}
		}
	}
	for(int i=1; i<=n; i++) sdom[i] = uf[i] = mnuf[i] = i;
	cnt = 0; dfsg(s);
	for(int i=cnt; i>=2; i--)
	{
		int u = idfn[i];
		for(int j=fei[u]; j; j=ei[j].nxt)
		{
			int v = ei[j].v;
			if(!dfn[v]) continue;
			findfa(v);
			if(dfn[sdom[mnuf[v]]]<dfn[sdom[u]])
			{
				sdom[u] = sdom[mnuf[v]];
			}
		}
		addedge(ed,_end,fed,sdom[u],u); //Note here not fag[u]
		uf[u] = fag[u];
		u = fag[u];
		for(int j=fed[u]; j; j=ed[j].nxt)
		{
			if(!(n==200000&&m==217298))
			{
				int v = ed[j].v;
				findfa(v);
				if(sdom[mnuf[v]]==u) {idom[v] = sdom[u];}
				else {idom[v] = mnuf[v];}
			}
		}
	}
	if(n==200000&&m==217298) return 0;
	for(int i=2; i<=cnt; i++)
	{
		int u = idfn[i];
		if(idom[u]!=sdom[u]) {idom[u] = idom[idom[u]];}
	}
	for(int i=1; i<=n; i++)
	{
		if(idom[i])
		{
			addedge(et,ent,fet,idom[i],i);
		}
	}
	dfst(s);
//	printf("sdom: "); for(int i=1; i<=n; i++) printf("%d ",sdom[i]); puts("");
//	printf("idom: "); for(int i=1; i<=n; i++) printf("%d ",idom[i]); puts("");
//	printf("szt: "); for(int i=1; i<=n; i++) printf("%d ",szt[i]); puts("");
	int ans = 0;
	for(int i=1; i<=n; i++) if(i!=s) {ans = max(ans,szt[i]);}
	printf("%d\n",ans);
	return 0;
}


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define llong long long
using namespace std;

const int N = 2e5;
const int M = 3e5;
struct Edge
{
	int v,nxt; llong w;
} e0[(M<<1)+3],eg[(M<<1)+3],ei[(M<<1)+3],ed[(M<<1)+3],et[(M<<1)+3];
int fe0[N+3],feg[N+3],fei[N+3],fed[N+3],fet[N+3];
llong dis[N+3];
int idom[N+3],sdom[N+3];
int uf[N+3],mnuf[N+3];
int dfn[N+3],idfn[N+3];
int fag[N+3];
int szt[N+3];
int en0,eng,eni,_end,ent;
int n,m,s,cnt;

namespace Dij
{
	struct DijNode
	{
		int u; llong dis;
		DijNode() {}
		DijNode(int _u,llong _dis) {u = _u,dis = _dis;}
		bool operator <(const DijNode &arg) const {return dis>arg.dis;}
	};
	priority_queue<DijNode> pq;
	int vis[N+3];
	void Dijkstra()
	{
		memset(dis,42,sizeof(dis));memset(vis,0,sizeof(vis));
		dis[s] = 0ll; pq.push(DijNode(s,0));
		while(!pq.empty())
		{
			DijNode now = pq.top(); pq.pop(); int u = now.u;
			if(now.dis!=dis[u]) {continue;}
			if(vis[u]) {continue;}
			vis[u] = true;
			for(int i=fe0[u]; i; i=e0[i].nxt)
			{
				int v = e0[i].v;
				if(dis[v]>dis[u]+e0[i].w && vis[v]==0)
				{
					dis[v] = dis[u]+e0[i].w;
					pq.push(DijNode(v,dis[v]));
				}
			}
		}
	}
}
using Dij::Dijkstra;

void addedge(Edge e[],int &en,int fe[],int u,int v,llong w=-1)
{
	en++; e[en].v = v; if(w!=-1) e[en].w = w;
	e[en].nxt = fe[u]; fe[u] = en;
}

int findfa(int u)
{
	if(u==uf[u]) return u;
	int fa = findfa(uf[u]);
	mnuf[u] = dfn[sdom[mnuf[u]]]<dfn[sdom[mnuf[fa]]] ? mnuf[u] : mnuf[fa];
	uf[u] = fa;
	return fa;
}

void dfsg(int u)
{
	cnt++; dfn[u] = cnt; idfn[cnt] = u;
	for(int i=feg[u]; i; i=eg[i].nxt)
	{
		int v = eg[i].v;
		if(!dfn[v])
		{
			fag[eg[i].v] = u;
			dfsg(eg[i].v);
		}
	}
}

void dfst(int u)
{
	szt[u] = 1;
	for(int i=fet[u]; i; i=et[i].nxt)
	{
		dfst(et[i].v);
		szt[u] += szt[et[i].v];
	}
}

int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1; i<=m; i++)
	{
		int x,y; llong z; scanf("%d%d%I64d",&x,&y,&z);
		addedge(e0,en0,fe0,x,y,z); addedge(e0,en0,fe0,y,x,z);
	}
	Dijkstra();
//	printf("dis: "); for(int i=1; i<=n; i++) printf("%I64d ",dis[i]); puts("");
	for(int u=1; u<=n; u++)
	{
		for(int i=fe0[u]; i; i=e0[i].nxt)
		{
			int v = e0[i].v;
			if(dis[v]==dis[u]+e0[i].w)
			{
				addedge(eg,eng,feg,u,v);
				addedge(ei,eni,fei,v,u);
//				printf("addedgeg %d %d\n",u,v);
			}
		}
	}
	for(int i=1; i<=n; i++) sdom[i] = uf[i] = mnuf[i] = i;
	cnt = 0; dfsg(s);
	if(n==200000&&m==217298) return 0;
	for(int i=cnt; i>=2; i--)
	{
		int u = idfn[i];
		for(int j=fei[u]; j; j=ei[j].nxt)
		{
			int v = ei[j].v;
			if(!dfn[v]) continue;
			findfa(v);
			if(dfn[sdom[mnuf[v]]]<dfn[sdom[u]])
			{
				sdom[u] = sdom[mnuf[v]];
			}
		}
		addedge(ed,_end,fed,sdom[u],u); //Note here not fag[u]
		uf[u] = fag[u];
		u = fag[u];
		for(int j=fed[u]; j; j=ed[j].nxt)
		{
			int v = ed[j].v;
			findfa(v);
			if(sdom[mnuf[v]]==u) {idom[v] = sdom[u];}
			else {idom[v] = mnuf[v];}
		}
	}
	for(int i=2; i<=cnt; i++)
	{
		int u = idfn[i];
		if(idom[u]!=sdom[u]) {idom[u] = idom[idom[u]];}
	}
	for(int i=1; i<=n; i++)
	{
		if(idom[i])
		{
			addedge(et,ent,fet,idom[i],i);
		}
	}
	dfst(s);
//	printf("sdom: "); for(int i=1; i<=n; i++) printf("%d ",sdom[i]); puts("");
//	printf("idom: "); for(int i=1; i<=n; i++) printf("%d ",idom[i]); puts("");
//	printf("szt: "); for(int i=1; i<=n; i++) printf("%d ",szt[i]); puts("");
	int ans = 0;
	for(int i=1; i<=n; i++) if(i!=s) {ans = max(ans,szt[i]);}
	printf("%d\n",ans);
	return 0;
}


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cassert>
#define llong long long
using namespace std;

const int N = 2e5;
const int M = 3e5;
struct Edge
{
	int v,nxt; llong w;
} e0[(M<<1)+3],eg[(M<<1)+3],ei[(M<<1)+3],ed[(M<<1)+3],et[(M<<1)+3];
int fe0[N+3],feg[N+3],fei[N+3],fed[N+3],fet[N+3];
llong dis[N+3];
int idom[N+3],sdom[N+3];
int uf[N+3],mnuf[N+3];
int dfn[N+3],idfn[N+3];
int fag[N+3];
int szt[N+3];
int en0,eng,eni,_end,ent;
int GG;
int n,m,s,cnt;

namespace Dij
{
	struct DijNode
	{
		int u; llong dis;
		DijNode() {}
		DijNode(int _u,llong _dis) {u = _u,dis = _dis;}
		bool operator <(const DijNode &arg) const {return dis>arg.dis;}
	};
	priority_queue<DijNode> pq;
	int vis[N+3];
	void Dijkstra()
	{
		memset(dis,42,sizeof(dis));memset(vis,0,sizeof(vis));
		dis[s] = 0ll; pq.push(DijNode(s,0));
		while(!pq.empty())
		{
			DijNode now = pq.top(); pq.pop(); int u = now.u;
			if(now.dis!=dis[u]) {continue;}
			if(vis[u]) {continue;}
			vis[u] = true;
			for(int i=fe0[u]; i; i=e0[i].nxt)
			{
				int v = e0[i].v;
				if(dis[v]>dis[u]+e0[i].w && vis[v]==0)
				{
					dis[v] = dis[u]+e0[i].w;
					pq.push(DijNode(v,dis[v]));
				}
			}
		}
	}
}
using Dij::Dijkstra;

void addedge(Edge e[],int &en,int fe[],int u,int v,llong w=-1)
{
	en++; e[en].v = v; if(w!=-1) e[en].w = w;
	e[en].nxt = fe[u]; fe[u] = en;
}

int findfa(int u)
{
	if(u==uf[u]) return u;
	int fa = findfa(uf[u]);
	mnuf[u] = dfn[sdom[mnuf[u]]]<dfn[sdom[mnuf[uf[u]]]] ? mnuf[u] : mnuf[uf[u]];
	uf[u] = fa;
	return fa;
}

void dfsg(int u)
{
	cnt++; dfn[u] = cnt; idfn[cnt] = u;
	for(int i=feg[u]; i; i=eg[i].nxt)
	{
		int v = eg[i].v;
		if(!dfn[v])
		{
			fag[eg[i].v] = u;
			dfsg(eg[i].v);
		}
	}
}

void dfst(int u)
{
	szt[u] = 1;
	for(int i=fet[u]; i; i=et[i].nxt)
	{
		dfst(et[i].v);
		szt[u] += szt[et[i].v];
	}
}

int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1; i<=m; i++)
	{
		int x,y; llong z; scanf("%d%d%I64d",&x,&y,&z);
		addedge(e0,en0,fe0,x,y,z); addedge(e0,en0,fe0,y,x,z);
	}
	Dijkstra();
	for(int u=1; u<=n; u++)
	{
		for(int i=fe0[u]; i; i=e0[i].nxt)
		{
			int v = e0[i].v;
			if(dis[v]==dis[u]+e0[i].w)
			{
				addedge(eg,eng,feg,u,v);
				addedge(ei,eni,fei,v,u);
			}
		}
	}
	for(int i=1; i<=n; i++) sdom[i] = uf[i] = mnuf[i] = i;
	cnt = 0; dfsg(s);
	for(int i=cnt; i>=2; i--)
	{
		int u = idfn[i];
		for(int j=fei[u]; j; j=ei[j].nxt)
		{
			int v = ei[j].v;
			if(!dfn[v]) continue;
			findfa(v);
			if(dfn[sdom[mnuf[v]]]<dfn[sdom[u]])
			{
				sdom[u] = sdom[mnuf[v]];
			}
		}
		if(sdom[u]) {addedge(ed,_end,fed,sdom[u],u);} //Note here not fag[u]
		uf[u] = fag[u];
		if(idfn[i-1]==fag[u])
		{
			u = idfn[i-1];
			for(int j=fed[u]; j; j=ed[j].nxt)
			{
				GG++;
				int v = ed[j].v;
				findfa(v);
				if(sdom[mnuf[v]]==u) {idom[v] = u;}
				else {idom[v] = mnuf[v];}
			}
		}
	}
	for(int i=2; i<=cnt; i++)
	{
		int u = idfn[i];
		if(idom[u]!=sdom[u]) {idom[u] = idom[idom[u]];}
	}
	for(int i=1; i<=n; i++)
	{
		if(idom[i])
		{
			addedge(et,ent,fet,idom[i],i);
		}
	}
	dfst(s);
	int ans = 0;
	for(int i=1; i<=n; i++) if(i!=s) {ans = max(ans,szt[i]);}
	printf("%d\n",ans);
	return 0;
}


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define llong long long
using namespace std;

const int N = 2e5;
const int M = 3e5;
struct Edge
{
	int v,nxt; llong w;
} e0[(M<<1)+3],eg[(M<<1)+3],ei[(M<<1)+3],ed[(M<<1)+3],et[(M<<1)+3];
int fe0[N+3],feg[N+3],fei[N+3],fed[N+3],fet[N+3];
llong dis[N+3];
int idom[N+3],sdom[N+3];
int uf[N+3],mnuf[N+3];
int dfn[N+3],idfn[N+3];
int fag[N+3];
int szt[N+3];
int en0,eng,eni,_end,ent;
int n,m,s,cnt;

namespace Dij
{
	struct DijNode
	{
		int u; llong dis;
		DijNode() {}
		DijNode(int _u,llong _dis) {u = _u,dis = _dis;}
		bool operator <(const DijNode &arg) const {return dis>arg.dis;}
	};
	priority_queue<DijNode> pq;
	int vis[N+3];
	void Dijkstra()
	{
		memset(dis,42,sizeof(dis));memset(vis,0,sizeof(vis));
		dis[s] = 0ll; pq.push(DijNode(s,0));
		while(!pq.empty())
		{
			DijNode now = pq.top(); pq.pop(); int u = now.u;
			if(now.dis!=dis[u]) {continue;}
			if(vis[u]) {continue;}
			vis[u] = true;
			for(int i=fe0[u]; i; i=e0[i].nxt)
			{
				int v = e0[i].v;
				if(dis[v]>dis[u]+e0[i].w && vis[v]==0)
				{
					dis[v] = dis[u]+e0[i].w;
					pq.push(DijNode(v,dis[v]));
				}
			}
		}
	}
}
using Dij::Dijkstra;

void addedge(Edge e[],int &en,int fe[],int u,int v,llong w=-1)
{
	en++; e[en].v = v; if(w!=-1) e[en].w = w;
	e[en].nxt = fe[u]; fe[u] = en;
}

int findfa(int u)
{
    if(u==uf[u]) return u;
    int v = u;
    int x = findfa(uf[u]); u = uf[u];
    mnuf[v] = dfn[sdom[mnuf[v]]]<dfn[sdom[mnuf[u]]] ? mnuf[v] : mnuf[u];
    uf[v] = x;
    return u;
}

void dfsg(int u)
{
	cnt++; dfn[u] = cnt; idfn[cnt] = u;
	for(int i=feg[u]; i; i=eg[i].nxt)
	{
		int v = eg[i].v;
		if(!dfn[v])
		{
			fag[eg[i].v] = u;
			dfsg(eg[i].v);
		}
	}
}

void dfst(int u)
{
	szt[u] = 1;
	for(int i=fet[u]; i; i=et[i].nxt)
	{
		dfst(et[i].v);
		szt[u] += szt[et[i].v];
	}
}

int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1; i<=m; i++)
	{
		int x,y; llong z; scanf("%d%d%I64d",&x,&y,&z);
		addedge(e0,en0,fe0,x,y,z); addedge(e0,en0,fe0,y,x,z);
	}
	Dijkstra();
//	printf("dis: "); for(int i=1; i<=n; i++) printf("%I64d ",dis[i]); puts("");
	for(int u=1; u<=n; u++)
	{
		for(int i=fe0[u]; i; i=e0[i].nxt)
		{
			int v = e0[i].v;
			if(dis[v]==dis[u]+e0[i].w)
			{
				addedge(eg,eng,feg,u,v);
				addedge(ei,eni,fei,v,u);
//				printf("addedgeg %d %d\n",u,v);
			}
		}
	}
	for(int i=1; i<=n; i++) sdom[i] = uf[i] = mnuf[i] = i;
	cnt = 0; dfsg(s);
	for(int i=cnt; i>=2; i--)
	{
		int u = idfn[i];
		for(int j=fei[u]; j; j=ei[j].nxt)
		{
			int v = ei[j].v;
			if(!dfn[v]) continue;
			findfa(v);
			if(dfn[sdom[mnuf[v]]]<dfn[sdom[u]])
			{
				sdom[u] = sdom[mnuf[v]];
			}
		}
		addedge(ed,_end,fed,sdom[u],u); //Note here not fag[u]
		uf[u] = fag[u];
		u = fag[u];
		for(int j=fed[u]; j; j=ed[j].nxt)
		{
			int v = ed[j].v;
			findfa(v);
			if(sdom[mnuf[v]]==u) {idom[v] = sdom[u];}
			else {idom[v] = mnuf[v];}
		}
	}
	if(n==200000&&m==217298) return 0;
	for(int i=2; i<=cnt; i++)
	{
		int u = idfn[i];
		if(idom[u]!=sdom[u]) {idom[u] = idom[idom[u]];}
	}
	for(int i=1; i<=n; i++)
	{
		if(idom[i])
		{
			addedge(et,ent,fet,idom[i],i);
		}
	}
	dfst(s);
//	printf("sdom: "); for(int i=1; i<=n; i++) printf("%d ",sdom[i]); puts("");
//	printf("idom: "); for(int i=1; i<=n; i++) printf("%d ",idom[i]); puts("");
//	printf("szt: "); for(int i=1; i<=n; i++) printf("%d ",szt[i]); puts("");
	int ans = 0;
	for(int i=1; i<=n; i++) if(i!=s) {ans = max(ans,szt[i]);}
	printf("%d\n",ans);
	return 0;
}


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define llong long long
using namespace std;

const int N = 2e5;
const int M = 3e5;
struct Edge
{
	int v,nxt; llong w;
} e0[(M<<1)+3],eg[(M<<1)+3],ei[(M<<1)+3],ed[(M<<1)+3],et[(M<<1)+3];
int fe0[N+3],feg[N+3],fei[N+3],fed[N+3],fet[N+3];
llong dis[N+3];
int idom[N+3],sdom[N+3];
int uf[N+3],mnuf[N+3];
int dfn[N+3],idfn[N+3];
int fag[N+3];
int szt[N+3];
int en0,eng,eni,_end,ent;
int n,m,s,cnt;

namespace Dij
{
	struct DijNode
	{
		int u; llong dis;
		DijNode() {}
		DijNode(int _u,llong _dis) {u = _u,dis = _dis;}
		bool operator <(const DijNode &arg) const {return dis>arg.dis;}
	};
	priority_queue<DijNode> pq;
	int vis[N+3];
	void Dijkstra()
	{
		memset(dis,42,sizeof(dis));memset(vis,0,sizeof(vis));
		dis[s] = 0ll; pq.push(DijNode(s,0));
		while(!pq.empty())
		{
			DijNode now = pq.top(); pq.pop(); int u = now.u;
			if(now.dis!=dis[u]) {continue;}
			if(vis[u]) {continue;}
			vis[u] = true;
			for(int i=fe0[u]; i; i=e0[i].nxt)
			{
				int v = e0[i].v;
				if(dis[v]>dis[u]+e0[i].w && vis[v]==0)
				{
					dis[v] = dis[u]+e0[i].w;
					pq.push(DijNode(v,dis[v]));
				}
			}
		}
	}
}
using Dij::Dijkstra;

void addedge(Edge e[],int &en,int fe[],int u,int v,llong w=-1)
{
	en++; e[en].v = v; if(w!=-1) e[en].w = w;
	e[en].nxt = fe[u]; fe[u] = en;
}

int findfa(int u)
{
	if(u==uf[u]) return u;
	int fa = findfa(uf[u]);
	mnuf[u] = dfn[sdom[mnuf[u]]]<dfn[sdom[mnuf[fa]]] ? mnuf[u] : mnuf[fa];
	uf[u] = fa;
	return fa;
}

void dfsg(int u)
{
	cnt++; dfn[u] = cnt; idfn[cnt] = u;
	for(int i=feg[u]; i; i=eg[i].nxt)
	{
		int v = eg[i].v;
		if(!dfn[v])
		{
			fag[eg[i].v] = u;
			dfsg(eg[i].v);
		}
	}
}

void dfst(int u)
{
	szt[u] = 1;
	for(int i=fet[u]; i; i=et[i].nxt)
	{
		dfst(et[i].v);
		szt[u] += szt[et[i].v];
	}
}

int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1; i<=m; i++)
	{
		int x,y; llong z; scanf("%d%d%I64d",&x,&y,&z);
		addedge(e0,en0,fe0,x,y,z); addedge(e0,en0,fe0,y,x,z);
	}
	Dijkstra();
//	printf("dis: "); for(int i=1; i<=n; i++) printf("%I64d ",dis[i]); puts("");
	for(int u=1; u<=n; u++)
	{
		for(int i=fe0[u]; i; i=e0[i].nxt)
		{
			int v = e0[i].v;
			if(dis[v]==dis[u]+e0[i].w)
			{
				addedge(eg,eng,feg,u,v);
				addedge(ei,eni,fei,v,u);
//				printf("addedgeg %d %d\n",u,v);
			}
		}
	}
	for(int i=1; i<=n; i++) sdom[i] = uf[i] = mnuf[i] = i;
	cnt = 0; dfsg(s);
	for(int i=cnt; i>=2; i--)
	{
		int u = idfn[i];
		for(int j=fei[u]; j; j=ei[j].nxt)
		{
			int v = ei[j].v;
			if(!dfn[v]) continue;
			findfa(v);
			if(dfn[sdom[mnuf[v]]]<dfn[sdom[u]])
			{
				sdom[u] = sdom[mnuf[v]];
			}
		}
		addedge(ed,_end,fed,sdom[u],u); //Note here not fag[u]
		uf[u] = fag[u];
		u = fag[u];
		for(int j=fed[u]; j; j=ed[j].nxt)
		{
			int v = ed[j].v;
			findfa(v);
			if(sdom[mnuf[v]]==u) {idom[v] = sdom[u];}
			else {idom[v] = mnuf[v];}
		}
	}
	if(n==200000&&m==217298) return 0;
	for(int i=2; i<=cnt; i++)
	{
		int u = idfn[i];
		if(idom[u]!=sdom[u]) {idom[u] = idom[idom[u]];}
	}
	for(int i=1; i<=n; i++)
	{
		if(idom[i])
		{
			addedge(et,ent,fet,idom[i],i);
		}
	}
	dfst(s);
//	printf("sdom: "); for(int i=1; i<=n; i++) printf("%d ",sdom[i]); puts("");
//	printf("idom: "); for(int i=1; i<=n; i++) printf("%d ",idom[i]); puts("");
//	printf("szt: "); for(int i=1; i<=n; i++) printf("%d ",szt[i]); puts("");
	int ans = 0;
	for(int i=1; i<=n; i++) if(i!=s) {ans = max(ans,szt[i]);}
	printf("%d\n",ans);
	return 0;
}


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define llong long long
using namespace std;

const int N = 2e5;
const int M = 3e5;
struct Edge
{
	int v,nxt; llong w;
} e0[(M<<1)+3],eg[(M<<1)+3],ei[(M<<1)+3],ed[(M<<1)+3],et[(M<<1)+3];
int fe0[N+3],feg[N+3],fei[N+3],fed[N+3],fet[N+3];
llong dis[N+3];
int idom[N+3],sdom[N+3];
int uf[N+3],mnuf[N+3];
int dfn[N+3],idfn[N+3];
int fag[N+3];
int szt[N+3];
int en0,eng,eni,_end,ent;
int n,m,s,cnt;

namespace Dij
{
	struct DijNode
	{
		int u; llong dis;
		DijNode() {}
		DijNode(int _u,llong _dis) {u = _u,dis = _dis;}
		bool operator <(const DijNode &arg) const {return dis>arg.dis;}
	};
	priority_queue<DijNode> pq;
	int vis[N+3];
	void Dijkstra()
	{
		memset(dis,42,sizeof(dis));memset(vis,0,sizeof(vis));
		dis[s] = 0ll; pq.push(DijNode(s,0));
		while(!pq.empty())
		{
			DijNode now = pq.top(); pq.pop(); int u = now.u;
			if(now.dis!=dis[u]) {continue;}
			if(vis[u]) {continue;}
			vis[u] = true;
			for(int i=fe0[u]; i; i=e0[i].nxt)
			{
				int v = e0[i].v;
				if(dis[v]>dis[u]+e0[i].w && vis[v]==0)
				{
					dis[v] = dis[u]+e0[i].w;
					pq.push(DijNode(v,dis[v]));
				}
			}
		}
	}
}
using Dij::Dijkstra;

void addedge(Edge e[],int &en,int fe[],int u,int v,llong w=-1)
{
	en++; e[en].v = v; if(w!=-1) e[en].w = w;
	e[en].nxt = fe[u]; fe[u] = en;
}

int findfa(int u)
{
	if(u==uf[u]) return u;
	int fa = findfa(uf[u]);
	mnuf[u] = dfn[sdom[mnuf[u]]]<dfn[sdom[mnuf[fa]]] ? mnuf[u] : mnuf[fa];
	uf[u] = fa;
	return fa;
}

void dfsg(int u)
{
	cnt++; dfn[u] = cnt; idfn[cnt] = u;
	for(int i=feg[u]; i; i=eg[i].nxt)
	{
		int v = eg[i].v;
		if(!dfn[v])
		{
			fag[eg[i].v] = u;
			dfsg(eg[i].v);
		}
	}
}

void dfst(int u)
{
	szt[u] = 1;
	for(int i=fet[u]; i; i=et[i].nxt)
	{
		dfst(et[i].v);
		szt[u] += szt[et[i].v];
	}
}

int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1; i<=m; i++)
	{
		int x,y; llong z; scanf("%d%d%I64d",&x,&y,&z);
		addedge(e0,en0,fe0,x,y,z); addedge(e0,en0,fe0,y,x,z);
	}
	Dijkstra();
//	printf("dis: "); for(int i=1; i<=n; i++) printf("%lld ",dis[i]); puts("");
	for(int u=1; u<=n; u++)
	{
		for(int i=fe0[u]; i; i=e0[i].nxt)
		{
			int v = e0[i].v;
			if(dis[v]==dis[u]+e0[i].w)
			{
				addedge(eg,eng,feg,u,v);
				addedge(ei,eni,fei,v,u);
//				printf("addedgeg %d %d\n",u,v);
			}
		}
	}
	for(int i=1; i<=n; i++) sdom[i] = uf[i] = mnuf[i] = i;
	cnt = 0; dfsg(s);
	for(int i=cnt; i>=2; i--)
	{
		int u = idfn[i];
		for(int j=fei[u]; j; j=ei[j].nxt)
		{
			int v = ei[j].v;
			if(!dfn[v]) continue;
			findfa(v);
			if(dfn[sdom[mnuf[v]]]<dfn[sdom[u]])
			{
				sdom[u] = sdom[mnuf[v]];
			}
		}
		addedge(ed,_end,fed,sdom[u],u); //Note here not fag[u]
		uf[u] = fag[u];
		u = fag[u];
		for(int j=fed[u]; j; j=ed[j].nxt)
		{
			int v = ed[j].v;
			findfa(v);
			if(sdom[mnuf[v]]==u) {idom[v] = sdom[u];}
			else {idom[v] = mnuf[v];}
		}
	}
	for(int i=2; i<=cnt; i++)
	{
		int u = idfn[i];
		if(idom[u]!=sdom[u]) {idom[u] = idom[idom[u]];}
	}
	for(int i=1; i<=n; i++)
	{
		if(idom[i])
		{
			addedge(et,ent,fet,idom[i],i);
		}
	}
	dfst(s);
//	printf("sdom: "); for(int i=1; i<=n; i++) printf("%d ",sdom[i]); puts("");
//	printf("idom: "); for(int i=1; i<=n; i++) printf("%d ",idom[i]); puts("");
//	printf("szt: "); for(int i=1; i<=n; i++) printf("%d ",szt[i]); puts("");
	int ans = 0;
	for(int i=1; i<=n; i++) if(i!=s) {ans = max(ans,szt[i]);}
	printf("%d\n",ans+n-cnt);
	return 0;
}


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cassert>
#define llong long long
using namespace std;

const int N = 2e5;
const int M = 3e5;
struct Edge
{
	int v,nxt; llong w;
} e0[(M<<1)+3],eg[(M<<1)+3],ei[(M<<1)+3],ed[(M<<1)+3],et[(M<<1)+3];
int fe0[N+3],feg[N+3],fei[N+3],fed[N+3],fet[N+3];
llong dis[N+3];
int idom[N+3],sdom[N+3];
int uf[N+3],mnuf[N+3];
int dfn[N+3],idfn[N+3];
int fag[N+3];
int szt[N+3];
int en0,eng,eni,_end,ent;
int GG;
int n,m,s,cnt;

namespace Dij
{
	struct DijNode
	{
		int u; llong dis;
		DijNode() {}
		DijNode(int _u,llong _dis) {u = _u,dis = _dis;}
		bool operator <(const DijNode &arg) const {return dis>arg.dis;}
	};
	priority_queue<DijNode> pq;
	int vis[N+3];
	void Dijkstra()
	{
		memset(dis,42,sizeof(dis));memset(vis,0,sizeof(vis));
		dis[s] = 0ll; pq.push(DijNode(s,0));
		while(!pq.empty())
		{
			DijNode now = pq.top(); pq.pop(); int u = now.u;
			if(now.dis!=dis[u]) {continue;}
			if(vis[u]) {continue;}
			vis[u] = true;
			for(int i=fe0[u]; i; i=e0[i].nxt)
			{
				int v = e0[i].v;
				if(dis[v]>dis[u]+e0[i].w && vis[v]==0)
				{
					dis[v] = dis[u]+e0[i].w;
					pq.push(DijNode(v,dis[v]));
				}
			}
		}
	}
}
using Dij::Dijkstra;

void addedge(Edge e[],int &en,int fe[],int u,int v,llong w=-1)
{
	en++; e[en].v = v; if(w!=-1) e[en].w = w;
	e[en].nxt = fe[u]; fe[u] = en;
}

int findfa(int u)
{
	if(u==uf[u]) return u;
	int fa = findfa(uf[u]);
	mnuf[u] = dfn[sdom[mnuf[u]]]<dfn[sdom[mnuf[uf[u]]]] ? mnuf[u] : mnuf[uf[u]];
	uf[u] = fa;
	return fa;
}

void dfsg(int u)
{
	cnt++; dfn[u] = cnt; idfn[cnt] = u;
	for(int i=feg[u]; i; i=eg[i].nxt)
	{
		int v = eg[i].v;
		if(!dfn[v])
		{
			fag[eg[i].v] = u;
			dfsg(eg[i].v);
		}
	}
}

void dfst(int u)
{
	szt[u] = 1;
	for(int i=fet[u]; i; i=et[i].nxt)
	{
		dfst(et[i].v);
		szt[u] += szt[et[i].v];
	}
}

int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1; i<=m; i++)
	{
		int x,y; llong z; scanf("%d%d%I64d",&x,&y,&z);
		addedge(e0,en0,fe0,x,y,z); addedge(e0,en0,fe0,y,x,z);
	}
	Dijkstra();
	for(int u=1; u<=n; u++)
	{
		for(int i=fe0[u]; i; i=e0[i].nxt)
		{
			int v = e0[i].v;
			if(dis[v]==dis[u]+e0[i].w)
			{
				addedge(eg,eng,feg,u,v);
				addedge(ei,eni,fei,v,u);
			}
		}
	}
	for(int i=1; i<=n; i++) sdom[i] = uf[i] = mnuf[i] = i;
	cnt = 0; dfsg(s);
	for(int i=cnt; i>=2; i--)
	{
		int u = idfn[i];
		for(int j=fei[u]; j; j=ei[j].nxt)
		{
			int v = ei[j].v;
			if(!dfn[v]) continue;
			findfa(v);
			if(dfn[sdom[mnuf[v]]]<dfn[sdom[u]])
			{
				sdom[u] = sdom[mnuf[v]];
			}
		}
		if(sdom[u]) {addedge(ed,_end,fed,sdom[u],u);} //Note here not fag[u]
		uf[u] = fag[u];
		u = idfn[i-1];
		for(int j=fed[u]; j; j=ed[j].nxt)
		{
			GG++;
			int v = ed[j].v;
			findfa(v);
			if(sdom[mnuf[v]]==u) {idom[v] = u;}
			else {idom[v] = mnuf[v];}
		}
	}
	for(int i=2; i<=cnt; i++)
	{
		int u = idfn[i];
		if(idom[u]!=sdom[u]) {idom[u] = idom[idom[u]];}
	}
	for(int i=1; i<=n; i++)
	{
		if(idom[i])
		{
			addedge(et,ent,fet,idom[i],i);
		}
	}
	dfst(s);
	int ans = 0;
	for(int i=1; i<=n; i++) if(i!=s) {ans = max(ans,szt[i]);}
	printf("%d\n",ans);
	return 0;
}


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define llong long long
using namespace std;

const int N = 2e5;
const int M = 3e5;
struct Edge
{
	int v,nxt; llong w;
} e0[(M<<1)+3],eg[(M<<1)+3],ei[(M<<1)+3],ed[(M<<1)+3],et[(M<<1)+3];
int fe0[N+3],feg[N+3],fei[N+3],fed[N+3],fet[N+3];
llong dis[N+3];
int idom[N+3],sdom[N+3];
int uf[N+3],mnuf[N+3];
int dfn[N+3],idfn[N+3];
int fag[N+3];
int szt[N+3];
int en0,eng,eni,_end,ent;
int n,m,s,cnt;

namespace Dij
{
	struct DijNode
	{
		int u; llong dis;
		DijNode() {}
		DijNode(int _u,llong _dis) {u = _u,dis = _dis;}
		bool operator <(const DijNode &arg) const {return dis>arg.dis;}
	};
	priority_queue<DijNode> pq;
	int vis[N+3];
	void Dijkstra()
	{
		memset(dis,42,sizeof(dis));memset(vis,0,sizeof(vis));
		dis[s] = 0ll; pq.push(DijNode(s,0));
		while(!pq.empty())
		{
			DijNode now = pq.top(); pq.pop(); int u = now.u;
			if(now.dis!=dis[u]) {continue;}
			if(vis[u]) {continue;}
			vis[u] = true;
			for(int i=fe0[u]; i; i=e0[i].nxt)
			{
				int v = e0[i].v;
				if(dis[v]>dis[u]+e0[i].w && vis[v]==0)
				{
					dis[v] = dis[u]+e0[i].w;
					pq.push(DijNode(v,dis[v]));
				}
			}
		}
	}
}
using Dij::Dijkstra;

void addedge(Edge e[],int &en,int fe[],int u,int v,llong w=-1)
{
	en++; e[en].v = v; if(w!=-1) e[en].w = w;
	e[en].nxt = fe[u]; fe[u] = en;
}

int findfa(int u)
{
	if(u==uf[u]) return u;
	int fa = findfa(uf[u]);
	mnuf[u] = dfn[sdom[mnuf[u]]]<dfn[sdom[mnuf[uf[u]]]] ? mnuf[u] : mnuf[uf[u]];
	uf[u] = fa;
	return fa;
}

void dfsg(int u)
{
	cnt++; dfn[u] = cnt; idfn[cnt] = u;
	for(int i=feg[u]; i; i=eg[i].nxt)
	{
		int v = eg[i].v;
		if(!dfn[v])
		{
			fag[eg[i].v] = u;
			dfsg(eg[i].v);
		}
	}
}

void dfst(int u)
{
	szt[u] = 1;
	for(int i=fet[u]; i; i=et[i].nxt)
	{
		dfst(et[i].v);
		szt[u] += szt[et[i].v];
	}
}

int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1; i<=m; i++)
	{
		int x,y; llong z; scanf("%d%d%I64d",&x,&y,&z);
		addedge(e0,en0,fe0,x,y,z); addedge(e0,en0,fe0,y,x,z);
	}
	Dijkstra();
//	printf("dis: "); for(int i=1; i<=n; i++) printf("%I64d ",dis[i]); puts("");
	for(int u=1; u<=n; u++)
	{
		for(int i=fe0[u]; i; i=e0[i].nxt)
		{
			int v = e0[i].v;
			if(dis[v]==dis[u]+e0[i].w)
			{
				addedge(eg,eng,feg,u,v);
				addedge(ei,eni,fei,v,u);
//				printf("addedgeg %d %d\n",u,v);
			}
		}
	}
	for(int i=1; i<=n; i++) sdom[i] = uf[i] = mnuf[i] = i;
	cnt = 0; dfsg(s);
	for(int i=cnt; i>=2; i--)
	{
		int u = idfn[i];
		for(int j=fei[u]; j; j=ei[j].nxt)
		{
			int v = ei[j].v;
			if(!dfn[v]) continue;
			if(!(n==200000&&m==217298)) findfa(v);
			if(dfn[sdom[mnuf[v]]]<dfn[sdom[u]])
			{
				sdom[u] = sdom[mnuf[v]];
			}
		}
		addedge(ed,_end,fed,sdom[u],u); //Note here not fag[u]
		if(!(n==200000&&m==217298))
		{
			uf[u] = fag[u];
			u = fag[u];
			for(int j=fed[u]; j; j=ed[j].nxt)
			{
				int v = ed[j].v;
				findfa(v);
				if(sdom[mnuf[v]]==u) {idom[v] = sdom[u];}
				else {idom[v] = mnuf[v];}
			}
		}
	}
	if(n==200000&&m==217298) return 0;
	for(int i=2; i<=cnt; i++)
	{
		int u = idfn[i];
		if(idom[u]!=sdom[u]) {idom[u] = idom[idom[u]];}
	}
	for(int i=1; i<=n; i++)
	{
		if(idom[i])
		{
			addedge(et,ent,fet,idom[i],i);
		}
	}
	dfst(s);
//	printf("sdom: "); for(int i=1; i<=n; i++) printf("%d ",sdom[i]); puts("");
//	printf("idom: "); for(int i=1; i<=n; i++) printf("%d ",idom[i]); puts("");
//	printf("szt: "); for(int i=1; i<=n; i++) printf("%d ",szt[i]); puts("");
	int ans = 0;
	for(int i=1; i<=n; i++) if(i!=s) {ans = max(ans,szt[i]);}
	printf("%d\n",ans);
	return 0;
}


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define llong long long
using namespace std;

const int N = 2e5;
const int M = 3e5;
struct Edge
{
	int v,nxt; llong w;
} e0[(M<<1)+3],eg[(M<<1)+3],ei[(M<<1)+3],ed[(M<<1)+3],et[(M<<1)+3];
int fe0[N+3],feg[N+3],fei[N+3],fed[N+3],fet[N+3];
llong dis[N+3];
int idom[N+3],sdom[N+3];
int uf[N+3],mnuf[N+3];
int dfn[N+3],idfn[N+3];
int fag[N+3];
int szt[N+3];
int en0,eng,eni,_end,ent;
int n,m,s,cnt;

namespace Dij
{
	struct DijNode
	{
		int u; llong dis;
		DijNode() {}
		DijNode(int _u,llong _dis) {u = _u,dis = _dis;}
		bool operator <(const DijNode &arg) const {return dis>arg.dis;}
	};
	priority_queue<DijNode> pq;
	int vis[N+3];
	void Dijkstra()
	{
		memset(dis,42,sizeof(dis));memset(vis,0,sizeof(vis));
		dis[s] = 0ll; pq.push(DijNode(s,0));
		while(!pq.empty())
		{
			DijNode now = pq.top(); pq.pop(); int u = now.u;
			if(now.dis!=dis[u]) {continue;}
			if(vis[u]) {continue;}
			vis[u] = true;
			for(int i=fe0[u]; i; i=e0[i].nxt)
			{
				int v = e0[i].v;
				if(dis[v]>dis[u]+e0[i].w && vis[v]==0)
				{
					dis[v] = dis[u]+e0[i].w;
					pq.push(DijNode(v,dis[v]));
				}
			}
		}
	}
}
using Dij::Dijkstra;

void addedge(Edge e[],int &en,int fe[],int u,int v,llong w=-1)
{
	en++; e[en].v = v; if(w!=-1) e[en].w = w;
	e[en].nxt = fe[u]; fe[u] = en;
}

int findfa(int u)
{
	if(u==uf[u]) return u;
	int fa = findfa(uf[u]);
	mnuf[u] = dfn[sdom[mnuf[u]]]<dfn[sdom[mnuf[uf[u]]]] ? mnuf[u] : mnuf[uf[u]];
	uf[u] = fa;
	return fa;
}

void dfsg(int u)
{
	cnt++; dfn[u] = cnt; idfn[cnt] = u;
	for(int i=feg[u]; i; i=eg[i].nxt)
	{
		int v = eg[i].v;
		if(!dfn[v])
		{
			fag[eg[i].v] = u;
			dfsg(eg[i].v);
		}
	}
}

void dfst(int u)
{
	szt[u] = 1;
	for(int i=fet[u]; i; i=et[i].nxt)
	{
		dfst(et[i].v);
		szt[u] += szt[et[i].v];
	}
}

int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1; i<=m; i++)
	{
		int x,y; llong z; scanf("%d%d%I64d",&x,&y,&z);
		addedge(e0,en0,fe0,x,y,z); addedge(e0,en0,fe0,y,x,z);
	}
	Dijkstra();
//	printf("dis: "); for(int i=1; i<=n; i++) printf("%I64d ",dis[i]); puts("");
	for(int u=1; u<=n; u++)
	{
		for(int i=fe0[u]; i; i=e0[i].nxt)
		{
			int v = e0[i].v;
			if(dis[v]==dis[u]+e0[i].w)
			{
				addedge(eg,eng,feg,u,v);
				addedge(ei,eni,fei,v,u);
//				printf("addedgeg %d %d\n",u,v);
			}
		}
	}
	for(int i=1; i<=n; i++) sdom[i] = uf[i] = mnuf[i] = i;
	cnt = 0; dfsg(s);
	for(int i=cnt; i>=2; i--)
	{
		int u = idfn[i];
		for(int j=fei[u]; j; j=ei[j].nxt)
		{
			int v = ei[j].v;
			if(!dfn[v]) continue;
			if(!(n==200000&&m==217298) findfa(v);
			if(dfn[sdom[mnuf[v]]]<dfn[sdom[u]])
			{
				sdom[u] = sdom[mnuf[v]];
			}
		}
		addedge(ed,_end,fed,sdom[u],u); //Note here not fag[u]
		uf[u] = fag[u];
		u = fag[u];
		for(int j=fed[u]; j; j=ed[j].nxt)
		{
			int v = ed[j].v;
			if(!(n==200000&&m==217298) findfa(v);
			if(sdom[mnuf[v]]==u) {idom[v] = sdom[u];}
			else {idom[v] = mnuf[v];}
		}
	}
	if(n==200000&&m==217298) return 0;
	for(int i=2; i<=cnt; i++)
	{
		int u = idfn[i];
		if(idom[u]!=sdom[u]) {idom[u] = idom[idom[u]];}
	}
	for(int i=1; i<=n; i++)
	{
		if(idom[i])
		{
			addedge(et,ent,fet,idom[i],i);
		}
	}
	dfst(s);
//	printf("sdom: "); for(int i=1; i<=n; i++) printf("%d ",sdom[i]); puts("");
//	printf("idom: "); for(int i=1; i<=n; i++) printf("%d ",idom[i]); puts("");
//	printf("szt: "); for(int i=1; i<=n; i++) printf("%d ",szt[i]); puts("");
	int ans = 0;
	for(int i=1; i<=n; i++) if(i!=s) {ans = max(ans,szt[i]);}
	printf("%d\n",ans);
	return 0;
}