#include <bits/stdc++.h>   using namespace std;   template <class T>   void debug(T a, T b) {     for (; a != b; ++a) cerr << *a <<    ;     cerr << endl;   }   template <class T>   void chmin(T& a, const T& b) {     if (a > b) a = b;   }   template <class T>   void chmax(T& a, const T& b) {     if (a < b) a = b;   }   namespace std {   template <class S, class T>   ostream& operator<<(ostream& out, const pair<S, T>& a) {     out <<  (  << a.first <<  ,  << a.second <<  ) ;     return out;   }   }  // namespace std   bool valid[200005];   struct DomTree {     static const int MAX_V = 200000;     int semi[MAX_V], U[MAX_V], idom[MAX_V];     int puf[MAX_V], par[MAX_V];     int mn[MAX_V];     void init() {       memset(puf, -1, sizeof(puf));       for (int i = 0; i < (MAX_V); ++i) mn[i] = i;     }     int root(int a) {       if (puf[a] == -1) return a;       int r = root(puf[a]);       if (semi[mn[puf[a]]] < semi[mn[a]]) mn[a] = mn[puf[a]];       return puf[a] = r;     }     void unite(int a, int b) { puf[b] = a; }     int eval(int v) {       root(v);       return mn[v];     }     int cnt;     int vs[MAX_V];     vector<int> bucket[MAX_V];     vector<int> g[MAX_V], rg[MAX_V];     void dfs(int v) {       semi[v] = cnt;       vs[cnt++] = v;       for (int u : g[v])         if (semi[u] < 0) {           par[u] = v;           dfs(u);         }     }     vector<int> g3[200005];     int size[200005];     int dfs3(int v) {       if (valid[v]) size[v] = 1;       for (auto to : g3[v]) {         size[v] += dfs3(to);       }       return size[v];     }     int solve(int n, int r, vector<int>* g_) {       init();       for (int i = 0; i < (n); ++i) {         g[i] = g_[i];         rg[i].clear();       }       for (int i = 0; i < (n); ++i)         for (auto to : g[i]) {           rg[to].push_back(i);         }       for (int i = 0; i < (n); ++i) semi[i] = -1;       cnt = 0;       dfs(r);       for (int i = n - 1; i > 0; i--) {         int w = vs[i];         for (int v : rg[w]) {           int u = eval(v);           chmin(semi[w], semi[u]);         }         bucket[vs[semi[w]]].push_back(w);         for (int v : bucket[par[w]]) U[v] = eval(v);         bucket[par[w]].clear();         unite(par[w], w);       }       for (int i = 1; i < n; i++) {         int w = vs[i];         int u = U[w];         if (semi[w] == semi[u])           idom[w] = semi[w];         else           idom[w] = idom[u];       }       for (int i = 1; i < n; i++) {         int w = vs[i];         idom[w] = vs[idom[w]];       }       idom[r] = -1;       for (int i = 0; i < (n); ++i)         if (i != r) g3[idom[i]].push_back(i);       dfs3(r);       int res = 0;       for (int i = 0; i < (n); ++i)         if (i != r) chmax(res, size[i]);       return res;     }   };   DomTree D;   int n, m, s;   vector<pair<int, int> > g[200005];   const long long int INF = 1e18;   long long int cost[200005];   vector<int> g2[200005];   int main() {     cin >> n >> m >> s;     --s;     for (int i = 0; i < (m); ++i) {       int a, b, c;       scanf( %d%d%d , &a, &b, &c);       --a;       --b;       g[a].push_back({b, c});       g[b].push_back({a, c});     }     for (int i = 0; i < (n); ++i) cost[i] = INF;     priority_queue<pair<long long int, int>, vector<pair<long long int, int> >,                    greater<pair<long long int, int> > >         pq;     pq.push({0, s});     cost[s] = 0;     while (!pq.empty()) {       pair<long long int, int> cur = pq.top();       pq.pop();       if (cost[cur.second] < cur.first) continue;       for (auto e : g[cur.second]) {         if (cost[e.first] > cur.first + e.second) {           cost[e.first] = cur.first + e.second;           pq.push({cost[e.first], e.first});         }       }     }     for (int i = 0; i < (n); ++i)       if (cost[i] < INF)         for (auto e : g[i]) {           if (cost[e.first] == cost[i] + e.second) g2[i].push_back(e.first);         }     for (int i = 0; i < (n); ++i)       if (cost[i] < INF) valid[i] = 1;     for (int i = 0; i < (n); ++i)       if (cost[i] == INF) g2[s].push_back(i);     int res = D.solve(n, s, g2);     cout << res << endl;     return 0;   }