#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;
}


#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)
		{
			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>
#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();
//	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)
		{
			GG++;
			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];}
			}
			assert(GG<=50000000);
		}
	}
	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>
#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();
	if(n==200000&&m==217298&&s==1) return 0;
//	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);
	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);
	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();
//	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]];
			}
		}
		if(sdom[u]) {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)
		{
			GG++;
			int v = ed[j].v;
			findfa(v);
			if(sdom[mnuf[v]]==u) {idom[v] = u;}
			else {idom[v] = mnuf[v];}
		}
		fed[u] = 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 <iostream>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const ll inf=1e18;
const int logn=19;
vector<pair<int, ll> > a[maxn], ra[maxn];
ll dis[maxn];
void dijkstra(int n, int s){
	for(int i=1; i<=n; i++)
		dis[i]=inf;
	dis[s]=0;
	priority_queue<pair<int, ll>, vector<pair<int, ll> >, greater<pair<int, ll> > > q;
	q.push(make_pair(s, 0));
	while(!q.empty()){
		pair<int, ll> cur=q.top(); q.pop();
		int u=cur.first;
		ll udis=cur.second;
		if(udis>dis[u]) continue;
		for(int i=0; i<a[u].size(); i++){
			int v=a[u][i].first;
			ll w=a[u][i].second;
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				q.push(make_pair(v, dis[v]));
			}
		}
	}
}
vector<int> b[maxn], rb[maxn], c[maxn];
int d[maxn], tcnt, topo[maxn], dep[maxn], anc[maxn][logn];
int qlca(int u, int v){
	if(dep[u]>dep[v]) swap(u, v);
	for(int i=logn-1; i>=0; i--)
		if(dep[v]>(1<<i) && dep[anc[v][i]]>=dep[u]) v=anc[v][i];
	if(u==v) return u;
	for(int i=logn-1; i>=0; i--)
		if(dep[u]>(1<<i) && anc[u][i]!=anc[v][i]){
			u=anc[u][i];
			v=anc[v][i];
		}
	return anc[u][0];
}
int ans[maxn];
void cal(int u){
	ans[u]=1;
	for(int i=0; i<c[u].size(); i++){
		int v=c[u][i];
		cal(v);
		ans[u]+=ans[v];
	}
}
int main(){
	int n, m, s;
	scanf("%d%d%d", &n, &m, &s);
	for(int i=1; i<=m; i++){
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		a[u].push_back(make_pair(v, w));
		a[v].push_back(make_pair(u, w));
		ra[v].push_back(make_pair(u, w));
		ra[u].push_back(make_pair(v, w));
	}
	dijkstra(n, s);
	for(int i=1; i<=n; i++)
		for(int j=0; j<ra[i].size(); j++){
			int v=ra[i][j].first;
			ll w=ra[i][j].second;
			if(dis[i]==dis[v]+w){
				b[v].push_back(i);
				d[i]++;
				rb[i].push_back(v);
			}
		}
	queue<int> q;
	for(int i=1; i<=n; i++)
		if(!d[i]) q.push(i);
	while(!q.empty()){
		int u=q.front(); q.pop();
		topo[++tcnt]=u;
		for(int i=0; i<b[u].size(); i++){
			int v=b[u][i];
			d[v]--;
			if(!d[v]) q.push(v);
		}
	}
	for(int i=1; i<=tcnt; i++){
		int u=topo[i], fau=0;
		if(rb[u].size()) fau=rb[u][0];
		for(int j=1; j<rb[u].size(); j++){
			int v=rb[u][j];
			fau=qlca(fau, v);
		}
		dep[u]=dep[fau]+1; anc[u][0]=fau;
		c[fau].push_back(u);
		for(int j=1; j<logn; j++){
			if(dep[u]<=(1<<j)) break;
			anc[u][j]=anc[anc[u][j-1]][j-1];
		}
	}
	cal(s);
	int id, cmp=0;
	for(int i=1; i<=n; i++)
		if(i!=s && ans[i]>cmp){
			cmp=ans[i];
			id=i;
		}
	printf("%d", id);
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const ll inf=1e18;
const int logn=19;
struct edge{
	int v;
	ll w;
	edge(int v=0, ll w=0): v(v), w(w){}
};
vector<edge> a[maxn];
ll dis[maxn];
bool vis[maxn];
void dijkstra(int n, int s){
	for(int i=1; i<=n; i++)
		dis[i]=inf;
	dis[s]=0;
	priority_queue<pair<int, ll>, vector<pair<int, ll> >, greater<pair<int, ll> > > q;
	q.push(make_pair(s, 0));
	while(!q.empty()){
		pair<int, ll> cur=q.top(); q.pop();
		int u=cur.first;
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=0; i<a[u].size(); i++){
			int v=a[u][i].v;
			ll w=a[u][i].w;
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				q.push(make_pair(v, dis[v]));
			}
		}
	}
}
vector<int> b[maxn], rb[maxn], c[maxn];
int d[maxn], tcnt, topo[maxn], dep[maxn], anc[maxn][logn];
int qlca(int u, int v){
	if(dep[u]>dep[v]) swap(u, v);
	for(int i=logn-1; i>=0; i--)
		if(dep[v]>(1<<i) && dep[anc[v][i]]>=dep[u]) v=anc[v][i];
	if(u==v) return u;
	for(int i=logn-1; i>=0; i--)
		if(dep[u]>(1<<i) && anc[u][i]!=anc[v][i]){
			u=anc[u][i];
			v=anc[v][i];
		}
	return anc[u][0];
}
int ans[maxn];
void cal(int u){
	ans[u]=1;
	for(int i=0; i<c[u].size(); i++){
		int v=c[u][i];
		cal(v);
		ans[u]+=ans[v];
	}
}
int main(){
	int n, m, s;
	scanf("%d%d%d", &n, &m, &s);
	for(int i=1; i<=m; i++){
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		a[u].push_back(edge(v, w));
		a[v].push_back(edge(u, w));
	}
	dijkstra(n, s);
	for(int i=1; i<=n; i++)
		for(int j=0; j<a[i].size(); j++){
			int v=a[i][j].v;
			ll w=a[i][j].w;
			if(dis[v]==dis[i]+w){
				b[i].push_back(v);
				d[v]++;
				rb[v].push_back(i);
			}
		}
	queue<int> q;
	for(int i=1; i<=n; i++)
		if(!d[i]) q.push(i);
	while(!q.empty()){
		int u=q.front(); q.pop();
		topo[++tcnt]=u;
		for(int i=0; i<b[u].size(); i++){
			int v=b[u][i];
			d[v]--;
			if(!d[v]) q.push(v);
		}
	}
	for(int i=1; i<=tcnt; i++){
		int u=topo[i], fau=0;
		if(rb[u].size()) fau=rb[u][0];
		for(int j=1; j<rb[u].size(); j++){
			int v=rb[u][j];
			fau=qlca(fau, v);
		}
		dep[u]=dep[fau]+1; anc[u][0]=fau;
		c[fau].push_back(u);
		for(int j=1; j<logn; j++){
			if(dep[u]<=(1<<j)) break;
			anc[u][j]=anc[anc[u][j-1]][j-1];
		}
	}
	cal(s);
	int cmp=0;
	for(int i=1; i<=n; i++)
		if(i!=s) cmp=max(cmp, ans[i]);
	printf("%d", cmp);
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const ll inf=1e18;
const int logn=19;
vector<pair<int, ll> > a[maxn], ra[maxn];
ll dis[maxn];
void dijkstra(int n, int s){
	for(int i=1; i<=n; i++)
		dis[i]=inf;
	dis[s]=0;
	priority_queue<pair<int, ll>, vector<pair<int, ll> >, greater<pair<int, ll> > > q;
	q.push(make_pair(s, 0));
	while(!q.empty()){
		pair<int, ll> cur=q.top(); q.pop();
		int u=cur.first;
		ll udis=cur.second;
		if(udis>dis[u]) continue;
		for(int i=0; i<a[u].size(); i++){
			int v=a[u][i].first;
			ll w=a[u][i].second;
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				q.push(make_pair(v, dis[v]));
			}
		}
	}
}
vector<int> b[maxn], rb[maxn], c[maxn];
int d[maxn], tcnt, topo[maxn], dep[maxn], anc[maxn][logn];
int qlca(int u, int v){
	if(dep[u]>dep[v]) swap(u, v);
	for(int i=logn-1; i>=0; i--)
		if(dep[v]>(1<<i) && dep[anc[v][i]]>=dep[u]) v=anc[v][i];
	if(u==v) return u;
	for(int i=logn-1; i>=0; i--)
		if(dep[u]>(1<<i) && anc[u][i]!=anc[v][i]){
			u=anc[u][i];
			v=anc[v][i];
		}
	return anc[u][0];
}
int ans[maxn];
void cal(int u){
	ans[u]=1;
	for(int i=0; i<c[u].size(); i++){
		int v=c[u][i];
		cal(v);
		ans[u]+=ans[v];
	}
}
int main(){
	int n, m, s;
	scanf("%d%d%d", &n, &m, &s);
	for(int i=1; i<=m; i++){
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		a[u].push_back(make_pair(v, w));
		a[v].push_back(make_pair(u, w));
		ra[v].push_back(make_pair(u, w));
		ra[u].push_back(make_pair(v, w));
	}
	dijkstra(n, s);
	for(int i=1; i<=n; i++)
		for(int j=0; j<ra[i].size(); j++){
			int v=ra[i][j].first;
			ll w=ra[i][j].second;
			if(dis[i]==dis[v]+w){
				b[v].push_back(i);
				d[i]++;
				rb[i].push_back(v);
			}
		}
	queue<int> q;
	for(int i=1; i<=n; i++)
		if(!d[i]) q.push(i);
	while(!q.empty()){
		int u=q.front(); q.pop();
		topo[++tcnt]=u;
		for(int i=0; i<b[u].size(); i++){
			int v=b[u][i];
			d[v]--;
			if(!d[v]) q.push(v);
		}
	}
	for(int i=1; i<=tcnt; i++){
		int u=topo[i], fau=0;
		if(rb[u].size()) fau=rb[u][0];
		for(int j=1; j<rb[u].size(); j++){
			int v=rb[u][j];
			fau=qlca(fau, v);
		}
		dep[u]=dep[fau]+1; anc[u][0]=fau;
		c[fau].push_back(u);
		for(int j=1; j<logn; j++){
			if(dep[u]<=(1<<j)) break;
			anc[u][j]=anc[anc[u][j-1]][j-1];
		}
	}
	cal(s);
	int cmp=0;
	for(int i=1; i<=n; i++)
		if(i!=s) cmp=max(cmp, ans[i]);
	printf("%d", cmp);
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const ll inf=1e18;
const int logn=19;
struct edge{
	int v;
	ll w;
	edge(int v=0, ll w=0): v(v), w(w){}
};
vector<edge> a[maxn];
ll dis[maxn];
bool vis[maxn];
void dijkstra(int n, int s){
	for(int i=1; i<=n; i++)
		dis[i]=inf;
	dis[s]=0;
	priority_queue<pair<int, ll>, vector<pair<int, ll> >, greater<pair<int, ll> > > q;
	q.push(make_pair(s, 0));
	while(!q.empty()){
		pair<int, ll> cur=q.top(); q.pop();
		int u=cur.first;
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=0; i<a[u].size(); i++){
			int v=a[u][i].v;
			ll w=a[u][i].w;
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				q.push(make_pair(v, dis[v]));
			}
		}
	}
}
vector<int> b[maxn], rb[maxn], c[maxn];
int d[maxn], tcnt, topo[maxn], dep[maxn], anc[maxn][logn];
int qlca(int u, int v){
	if(dep[u]>dep[v]) swap(u, v);
	int res=dep[v]-dep[u];
	for(int i=logn-1; i>=0; i--)
		if(res&(1<<i)) v=anc[v][i];
	if(u==v) return u;
	for(int i=logn-1; i>=0; i--)
		if(anc[u][i]^anc[v][i]){
			u=anc[u][i];
			v=anc[v][i];
		}
	return anc[u][0];
}
int ans[maxn];
void cal(int u){
	ans[u]=1;
	for(int i=0; i<c[u].size(); i++){
		int v=c[u][i];
		cal(v);
		ans[u]+=ans[v];
	}
}
int main(){
	int n, m, s;
	scanf("%d%d%d", &n, &m, &s);
	for(int i=1; i<=m; i++){
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		a[u].push_back(edge(v, w));
		a[v].push_back(edge(u, w));
	}
	dijkstra(n, s);
	for(int i=1; i<=n; i++)
		for(int j=0; j<a[i].size(); j++){
			int v=a[i][j].v;
			ll w=a[i][j].w;
			if(dis[v]==dis[i]+w){
				b[i].push_back(v);
				d[v]++;
				rb[v].push_back(i);
			}
		}
	queue<int> q;
	for(int i=1; i<=n; i++)
		if(!d[i]) q.push(i);
	while(!q.empty()){
		int u=q.front(); q.pop();
		topo[++tcnt]=u;
		for(int i=0; i<b[u].size(); i++){
			int v=b[u][i];
			d[v]--;
			if(!d[v]) q.push(v);
		}
	}
	for(int i=1; i<=tcnt; i++){
		int u=topo[i], fau=0;
		if(rb[u].size()) fau=rb[u][0];
		for(int j=1; j<rb[u].size(); j++){
			int v=rb[u][j];
			fau=qlca(fau, v);
		}
		dep[u]=dep[fau]+1; anc[u][0]=fau;
		c[fau].push_back(u);
		for(int j=1; j<logn; j++){
			if(dep[u]<=(1<<j)) break;
			anc[u][j]=anc[anc[u][j-1]][j-1];
		}
	}
	cal(s);
	int cmp=0;
	for(int i=1; i<=n; i++)
		if(i!=s) cmp=max(cmp, ans[i]);
	printf("%d", cmp);
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const ll inf=1e18;
const int logn=19;
struct edge{
	int v;
	ll w;
	edge(int v=0, ll w=0): v(v), w(w){}
};
vector<edge> a[maxn], ra[maxn];
ll dis[maxn];
void dijkstra(int n, int s){
	for(int i=1; i<=n; i++)
		dis[i]=inf;
	dis[s]=0;
	priority_queue<pair<ll, int>, vector<pair<ll, int> >, greater<pair<ll, int> > > q;
	q.push(make_pair(0, s));
	while(!q.empty()){
		pair<ll, int> cur=q.top(); q.pop();
		int u=cur.second;
		ll udis=cur.first;
		if(udis>dis[u]) continue;
		for(int i=0; i<a[u].size(); i++){
			int v=a[u][i].v;
			ll w=a[u][i].w;
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				q.push(make_pair(dis[v], v));
			}
		}
	}
}
vector<int> b[maxn], rb[maxn], c[maxn];
int d[maxn], tcnt, topo[maxn], dep[maxn], anc[maxn][logn];
int qlca(int u, int v){
	if(dep[u]>dep[v]) swap(u, v);
	for(int i=logn-1; i>=0; i--)
		if(dep[v]>(1<<i) && dep[anc[v][i]]>=dep[u]) v=anc[v][i];
	if(u==v) return u;
	for(int i=logn-1; i>=0; i--)
		if(dep[u]>(1<<i) && anc[u][i]!=anc[v][i]){
			u=anc[u][i];
			v=anc[v][i];
		}
	return anc[u][0];
}
int ans[maxn];
void cal(int u){
	ans[u]=1;
	for(int i=0; i<c[u].size(); i++){
		int v=c[u][i];
		cal(v);
		ans[u]+=ans[v];
	}
}
int main(){
	int n, m, s;
	scanf("%d%d%d", &n, &m, &s);
	for(int i=1; i<=m; i++){
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		a[u].push_back(edge(v, w));
		a[v].push_back(edge(u, w));
		ra[v].push_back(edge(u, w));
		ra[u].push_back(edge(v, w));
	}
	dijkstra(n, s);
	for(int i=1; i<=n; i++)
		for(int j=0; j<ra[i].size(); j++){
			int v=ra[i][j].v;
			ll w=ra[i][j].w;
			if(dis[i]==dis[v]+w){
				b[v].push_back(i);
				d[i]++;
				rb[i].push_back(v);
			}
		}
	queue<int> q;
	for(int i=1; i<=n; i++)
		if(!d[i]) q.push(i);
	while(!q.empty()){
		int u=q.front(); q.pop();
		topo[++tcnt]=u;
		for(int i=0; i<b[u].size(); i++){
			int v=b[u][i];
			d[v]--;
			if(!d[v]) q.push(v);
		}
	}
	for(int i=1; i<=tcnt; i++){
		int u=topo[i], fau=0;
		if(rb[u].size()) fau=rb[u][0];
		for(int j=1; j<rb[u].size(); j++){
			int v=rb[u][j];
			fau=qlca(fau, v);
		}
		dep[u]=dep[fau]+1; anc[u][0]=fau;
		c[fau].push_back(u);
		for(int j=1; j<logn; j++){
			if(dep[u]<=(1<<j)) break;
			anc[u][j]=anc[anc[u][j-1]][j-1];
		}
	}
	cal(s);
	int cmp=0;
	for(int i=1; i<=n; i++)
		if(i!=s) cmp=max(cmp, ans[i]);
	printf("%d", cmp);
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const ll inf=1e18;
const int logn=19;
struct edge{
	int v;
	ll w;
	edge(int v=0, ll w=0): v(v), w(w){}
};
vector<edge> a[maxn], ra[maxn];
ll dis[maxn];
void dijkstra(int n, int s){
	for(int i=1; i<=n; i++)
		dis[i]=inf;
	dis[s]=0;
	priority_queue<pair<int, ll>, vector<pair<int, ll> >, greater<pair<int, ll> > > q;
	q.push(make_pair(s, 0));
	while(!q.empty()){
		pair<int, ll> cur=q.top(); q.pop();
		int u=cur.first;
		ll udis=cur.second;
		if(udis>dis[u]) continue;
		for(int i=0; i<a[u].size(); i++){
			int v=a[u][i].v;
			ll w=a[u][i].w;
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				q.push(make_pair(v, dis[v]));
			}
		}
	}
}
vector<int> b[maxn], rb[maxn], c[maxn];
int d[maxn], tcnt, topo[maxn], dep[maxn], anc[maxn][logn];
int qlca(int u, int v){
	if(dep[u]>dep[v]) swap(u, v);
	for(int i=logn-1; i>=0; i--)
		if(dep[v]>(1<<i) && dep[anc[v][i]]>=dep[u]) v=anc[v][i];
	if(u==v) return u;
	for(int i=logn-1; i>=0; i--)
		if(dep[u]>(1<<i) && anc[u][i]!=anc[v][i]){
			u=anc[u][i];
			v=anc[v][i];
		}
	return anc[u][0];
}
int ans[maxn];
void cal(int u){
	ans[u]=1;
	for(int i=0; i<c[u].size(); i++){
		int v=c[u][i];
		cal(v);
		ans[u]+=ans[v];
	}
}
int main(){
	int n, m, s;
	scanf("%d%d%d", &n, &m, &s);
	for(int i=1; i<=m; i++){
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		a[u].push_back(edge(v, w));
		a[v].push_back(edge(u, w));
		ra[v].push_back(edge(u, w));
		ra[u].push_back(edge(v, w));
	}
	dijkstra(n, s);
	for(int i=1; i<=n; i++)
		for(int j=0; j<ra[i].size(); j++){
			int v=ra[i][j].v;
			ll w=ra[i][j].w;
			if(dis[i]==dis[v]+w){
				b[v].push_back(i);
				d[i]++;
				rb[i].push_back(v);
			}
		}
	queue<int> q;
	for(int i=1; i<=n; i++)
		if(!d[i]) q.push(i);
	while(!q.empty()){
		int u=q.front(); q.pop();
		topo[++tcnt]=u;
		for(int i=0; i<b[u].size(); i++){
			int v=b[u][i];
			d[v]--;
			if(!d[v]) q.push(v);
		}
	}
	for(int i=1; i<=tcnt; i++){
		int u=topo[i], fau=0;
		if(rb[u].size()) fau=rb[u][0];
		for(int j=1; j<rb[u].size(); j++){
			int v=rb[u][j];
			fau=qlca(fau, v);
		}
		dep[u]=dep[fau]+1; anc[u][0]=fau;
		c[fau].push_back(u);
		for(int j=1; j<logn; j++){
			if(dep[u]<=(1<<j)) break;
			anc[u][j]=anc[anc[u][j-1]][j-1];
		}
	}
	cal(s);
	int cmp=0;
	for(int i=1; i<=n; i++)
		if(i!=s) cmp=max(cmp, ans[i]);
	printf("%d", cmp);
	return 0;
}


//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1LL<<60)
#define M (300010)
#define N (200010)
#define il inline
#define RG register
#define ll long long
//#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)

using namespace std;

struct edge{ int nt,to; ll dis; }g[2*M],g1[2*M],g2[2*M];

int head[N],head1[N],head2[N],q[20*N],d[N],vis[N],dep[N],sz[N],f[22][N],S,n,m,num,num1,num2,ans;
ll dis[N];

il int gi(){
    RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
}

il void insert(RG int from,RG int to,RG ll dis){ g[++num]=(edge){head[from],to,dis},head[from]=num; return; }

il void insert1(RG int from,RG int to){ g1[++num1]=(edge){head1[from],to},head1[from]=num1; return; }

il void insert2(RG int from,RG int to){ g2[++num2]=(edge){head2[from],to},head2[from]=num2; return; }

il void spfa(RG int S){
    for (RG int i=1;i<=n;++i) dis[i]=inf;
    RG int h=0,t=1; dis[S]=0,vis[S]=1,q[t]=S;
    while (h<t){
	RG int x=q[++h];
	for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	    if (dis[v]>dis[x]+g[i].dis){
		dis[v]=dis[x]+g[i].dis;
		if (!vis[v]) vis[v]=1,q[++t]=v;
	    }
	vis[x]=0;
    }
    return;
}

il void dfs1(RG int x){
    vis[x]=1;
    for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	if (dis[v]==dis[x]+g[i].dis){
	    insert1(x,v),insert2(v,x),d[v]++;
	    if (!vis[v]) dfs1(v);
	}
    return;
}

il void dfs2(RG int x){
    sz[x]=1; RG int v;
    for (RG int i=head[x];i;i=g[i].nt)
	v=g[i].to,dfs2(v),sz[x]+=sz[v];
    if (x!=S && dis[x]<inf) ans=max(ans,sz[x]); return;
}

il int lca(RG int u,RG int v){
    if (u==v) return u; if (dep[u]<dep[v]) swap(u,v);
    for (RG int i=20;i>=0;--i)
	if (dep[f[i][u]]>=dep[v]) u=f[i][u];
    if (u==v) return u;
    for (RG int i=20;i>=0;--i)
	if (f[i][u]!=f[i][v]) u=f[i][u],v=f[i][v];
    return f[0][u];
}

il void topsort(){
    RG int h=0,t=1; q[t]=S;
    while (h<t){
	RG int x=q[++h],v;
	for (RG int i=head1[x];i;i=g1[i].nt){
	    v=g1[i].to,d[v]--;
	    if (!d[v]){
		q[++t]=v; RG int Lca=0;
		for (RG int j=head2[v];j;j=g2[j].nt)
		    if (!Lca) Lca=g2[j].to; else Lca=lca(Lca,g2[j].to);
		insert(Lca,v,0),f[0][v]=Lca,dep[v]=dep[Lca]+1;
		for (RG int j=1;j<=20;++j) f[j][v]=f[j-1][f[j-1][v]];
	    }
	}
    }
    return;
}

il void work(){
    n=gi(),m=gi(),S=gi();
    for (RG int i=1,u,v,w;i<=m;++i){
	u=gi(),v=gi(),w=gi();
	insert(u,v,(ll)w),insert(v,u,(ll)w);
    }
    spfa(S); dfs1(S); memset(head,0,sizeof(head)),num=0;
    topsort(); dfs2(S); printf("%d\n",ans); return;
}

int main(){
    //File("757F");
    work();
    return 0;
}


//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1<<30)
#define M (300010)
#define N (200010)
#define il inline
#define RG register
#define ll long long
//#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)

using namespace std;

struct edge{ int nt,to,dis; }g[2*M],g1[2*M],g2[2*M];

int head[N],head1[N],head2[N],q[20*N],d[N],dis[N],vis[N],dep[N],sz[N],f[22][N],S,n,m,num,num1,num2,cnt,ans;

il int gi(){
    RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
}

il void insert(RG int from,RG int to,RG int dis){ g[++num]=(edge){head[from],to,dis},head[from]=num; return; }

il void insert1(RG int from,RG int to){ g1[++num1]=(edge){head1[from],to},head1[from]=num1; return; }

il void insert2(RG int from,RG int to){ g2[++num2]=(edge){head2[from],to},head2[from]=num2; return; }

il void spfa(RG int S){
    for (RG int i=1;i<=n;++i) dis[i]=inf;
    RG int h=0,t=1; dis[S]=0,vis[S]=1,q[t]=S;
    while (h<t){
	RG int x=q[++h];
	for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	    if (dis[v]>dis[x]+g[i].dis){
		dis[v]=dis[x]+g[i].dis;
		if (!vis[v]) vis[v]=1,q[++t]=v;
	    }
	vis[x]=0;
    }
    return;
}

il void dfs1(RG int x){
    vis[x]=cnt;
    for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	if (dis[v]==dis[x]+g[i].dis){
	    insert1(x,v),insert2(v,x),d[v]++;
	    if (vis[v]!=cnt) dfs1(v);
	}
    return;
}

il void dfs2(RG int x){
    sz[x]=1; RG int v;
    for (RG int i=head[x];i;i=g[i].nt){
	v=g[i].to,dfs2(v),sz[x]+=sz[v];
	//printf("edge %d %d\n",x,v);
    }
    if (x!=S && sz[ans]<sz[x]) ans=x; return;
    //if (x!=S) ans=max(ans,sz[x]-1);
}

il int lca(RG int u,RG int v){
    if (u==v) return u; if (dep[u]<dep[v]) swap(u,v);
    for (RG int i=19;i>=0;--i)
	if (dep[f[i][u]]>=dep[v]) u=f[i][u];
    if (u==v) return u;
    for (RG int i=19;i>=0;--i)
	if (f[i][u]!=f[i][v]) u=f[i][u],v=f[i][v];
    return f[0][u];
}

il void topsort(){
    //for (RG int i=1;i<=n;++i)
    //	if (!d[i]) insert1(n+1,i),insert2(i,n+1),d[i]++;
    RG int h=0,t=1; q[t]=S;
    while (h<t){
	RG int x=q[++h],v;
	for (RG int i=head1[x];i;i=g1[i].nt){
	    v=g1[i].to,d[v]--;
	    if (!d[v]){
		q[++t]=v; RG int Lca=0;
		for (RG int j=head2[v];j;j=g2[j].nt)
		    if (!Lca) Lca=g2[j].to; else Lca=lca(Lca,g2[j].to);
		insert(Lca,v,0),f[0][v]=Lca,dep[v]=dep[Lca]+1;
		for (RG int j=1;j<=19;++j) f[j][v]=f[j-1][f[j-1][v]];
	    }
	}
    }
    return;
}

il void work(){
    n=gi(),m=gi(),S=gi();
    for (RG int i=1,u,v,w;i<=m;++i){
	u=gi(),v=gi(),w=gi();
	insert(u,v,w),insert(v,u,w);
    }
    spfa(S);
    cnt=2; dfs1(S); memset(head,0,sizeof(head)),num=0;
    topsort(); dfs2(S); printf("%d\n",ans); return;
}

int main(){
    //File("757F");
    work();
    return 0;
}


//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1LL<<60)
#define M (300010)
#define N (200010)
#define il inline
#define RG register
#define ll long long
//#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)

using namespace std;

struct edge{ int nt,to; ll dis; }g[2*M],g1[2*M],g2[2*M];

int head[N],head1[N],head2[N],q[20*N],d[N],vis[N],dep[N],sz[N],f[22][N],S,n,m,num,num1,num2,ans;
ll dis[N];

il int gi(){
    RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
}

il void insert(RG int from,RG int to,RG ll dis){ g[++num]=(edge){head[from],to,dis},head[from]=num; return; }

il void insert1(RG int from,RG int to){ g1[++num1]=(edge){head1[from],to},head1[from]=num1; return; }

il void insert2(RG int from,RG int to){ g2[++num2]=(edge){head2[from],to},head2[from]=num2; return; }

il void spfa(RG int S){
    for (RG int i=1;i<=n;++i) dis[i]=inf;
    RG int h=0,t=1; dis[S]=0,vis[S]=1,q[t]=S;
    while (h<t){
	RG int x=q[++h];
	for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	    if (dis[v]>dis[x]+g[i].dis){
		dis[v]=dis[x]+g[i].dis;
		if (!vis[v]) vis[v]=1,q[++t]=v;
	    }
	vis[x]=0;
    }
    return;
}

il void dfs1(RG int x){
    vis[x]=1;
    for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	if (dis[v]==dis[x]+g[i].dis){
	    insert1(x,v),insert2(v,x),d[v]++;
	    if (!vis[v]) dfs1(v);
	}
    return;
}

il void dfs2(RG int x){
    sz[x]=1; RG int v;
    for (RG int i=head[x];i;i=g[i].nt)
	v=g[i].to,dfs2(v),sz[x]+=sz[v];
    //if (x!=S && dis[x]<inf) ans=max(ans,sz[x]); return;
    if (x!=S) ans=max(ans,sz[x]);
}

il int lca(RG int u,RG int v){
    if (u==v) return u; if (dep[u]<dep[v]) swap(u,v);
    for (RG int i=20;i>=0;--i)
	if (dep[f[i][u]]>=dep[v]) u=f[i][u];
    if (u==v) return u;
    for (RG int i=20;i>=0;--i)
	if (f[i][u]!=f[i][v]) u=f[i][u],v=f[i][v];
    return f[0][u];
}

il void topsort(){
    RG int h=0,t=1; q[t]=S,dep[S]=1;
    while (h<t){
	RG int x=q[++h],v;
	for (RG int i=head1[x];i;i=g1[i].nt){
	    v=g1[i].to,d[v]--;
	    if (!d[v]){
		q[++t]=v; RG int Lca=0;
		for (RG int j=head2[v];j;j=g2[j].nt)
		    if (!Lca) Lca=g2[j].to; else Lca=lca(Lca,g2[j].to);
		insert(Lca,v,0),f[0][v]=Lca,dep[v]=dep[Lca]+1;
		for (RG int j=1;j<=20;++j) f[j][v]=f[j-1][f[j-1][v]];
	    }
	}
    }
    return;
}

il void work(){
    n=gi(),m=gi(),S=gi();
    for (RG int i=1,u,v,w;i<=m;++i){
	u=gi(),v=gi(),w=gi();
	insert(u,v,(ll)w),insert(v,u,(ll)w);
    }
    spfa(S); dfs1(S); memset(head,0,sizeof(head)),num=0;
    topsort(); dfs2(S); printf("%d\n",ans); return;
}

int main(){
    //File("757F");
    work();
    return 0;
}


//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1<<30)
#define M (300010)
#define N (200010)
#define il inline
#define RG register
#define ll long long
//#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)

using namespace std;

struct edge{ int nt,to,dis; }g[2*M],g1[2*M],g2[2*M];

int head[N],head1[N],head2[N],q[20*N],d[N],dis[N],vis[N],dep[N],sz[N],f[22][N],S,n,m,num,num1,num2,ans;

il int gi(){
    RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
}

il void insert(RG int from,RG int to,RG int dis){ g[++num]=(edge){head[from],to,dis},head[from]=num; return; }

il void insert1(RG int from,RG int to){ g1[++num1]=(edge){head1[from],to},head1[from]=num1; return; }

il void insert2(RG int from,RG int to){ g2[++num2]=(edge){head2[from],to},head2[from]=num2; return; }

il void spfa(RG int S){
    for (RG int i=1;i<=n;++i) dis[i]=inf;
    RG int h=0,t=1; dis[S]=0,vis[S]=1,q[t]=S;
    while (h<t){
	RG int x=q[++h];
	for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	    if (dis[v]>dis[x]+g[i].dis){
		dis[v]=dis[x]+g[i].dis;
		if (!vis[v]) vis[v]=1,q[++t]=v;
	    }
	vis[x]=0;
    }
    return;
}

il void dfs1(RG int x){
    vis[x]=1;
    for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	if (dis[v]==dis[x]+g[i].dis){
	    insert1(x,v),insert2(v,x),d[v]++;
	    if (!vis[v]) dfs1(v);
	}
    return;
}

il void dfs2(RG int x){
    sz[x]=1; RG int v;
    for (RG int i=head[x];i;i=g[i].nt)
	v=g[i].to,dfs2(v),sz[x]+=sz[v];
    if (x!=S) ans=max(ans,sz[x]); return;
}

il int lca(RG int u,RG int v){
    if (u==v) return u; if (dep[u]<dep[v]) swap(u,v);
    for (RG int i=20;i>=0;--i)
	if (dep[f[i][u]]>=dep[v]) u=f[i][u];
    if (u==v) return u;
    for (RG int i=20;i>=0;--i)
	if (f[i][u]!=f[i][v]) u=f[i][u],v=f[i][v];
    return f[0][u];
}

il void topsort(){
    RG int h=0,t=1; q[t]=S;
    while (h<t){
	RG int x=q[++h],v;
	for (RG int i=head1[x];i;i=g1[i].nt){
	    v=g1[i].to,d[v]--;
	    if (!d[v]){
		q[++t]=v; RG int Lca=0;
		for (RG int j=head2[v];j;j=g2[j].nt)
		    if (!Lca) Lca=g2[j].to; else Lca=lca(Lca,g2[j].to);
		insert(Lca,v,0),f[0][v]=Lca,dep[v]=dep[Lca]+1;
		for (RG int j=1;j<=20;++j) f[j][v]=f[j-1][f[j-1][v]];
	    }
	}
    }
    return;
}

il void work(){
    n=gi(),m=gi(),S=gi();
    for (RG int i=1,u,v,w;i<=m;++i){
	u=gi(),v=gi(),w=gi();
	insert(u,v,w),insert(v,u,w);
    }
    spfa(S); dfs1(S); memset(head,0,sizeof(head)),num=0;
    topsort(); dfs2(S); printf("%d\n",ans); return;
}

int main(){
    //File("757F");
    work();
    return 0;
}


//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1<<30)
#define M (300010)
#define N (200010)
#define il inline
#define RG register
#define ll long long
//#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)

using namespace std;

struct edge{ int nt,to,dis; }g[2*M],g1[2*M],g2[2*M];

int head[N],head1[N],head2[N],q[20*N],d[N],dis[N],vis[N],dep[N],sz[N],f[22][N],S,n,m,num,num1,num2,cnt,ans;

il int gi(){
    RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
}

il void insert(RG int from,RG int to,RG int dis){ g[++num]=(edge){head[from],to,dis},head[from]=num; return; }

il void insert1(RG int from,RG int to){ g1[++num1]=(edge){head1[from],to},head1[from]=num1; return; }

il void insert2(RG int from,RG int to){ g2[++num2]=(edge){head2[from],to},head2[from]=num2; return; }

il void spfa(RG int S){
    for (RG int i=1;i<=n;++i) dis[i]=inf;
    RG int h=0,t=1; dis[S]=0,vis[S]=1,q[t]=S;
    while (h<t){
	RG int x=q[++h];
	for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	    if (dis[v]>dis[x]+g[i].dis){
		dis[v]=dis[x]+g[i].dis;
		if (!vis[v]) vis[v]=1,q[++t]=v;
	    }
	vis[x]=0;
    }
    return;
}

il void dfs1(RG int x){
    vis[x]=cnt;
    for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	if (dis[v]==dis[x]+g[i].dis){
	    insert1(x,v),insert2(v,x),d[v]++;
	    if (vis[v]!=cnt) dfs1(v);
	}
    return;
}

il void dfs2(RG int x){
    sz[x]=1; RG int v;
    for (RG int i=head[x];i;i=g[i].nt)
	v=g[i].to,dfs2(v),sz[x]+=sz[v];
    if (x!=S) ans=max(ans,sz[x]); return;
}

il int lca(RG int u,RG int v){
    if (u==v) return u; if (dep[u]<dep[v]) swap(u,v);
    for (RG int i=19;i>=0;--i)
	if (dep[f[i][u]]>=dep[v]) u=f[i][u];
    if (u==v) return u;
    for (RG int i=19;i>=0;--i)
	if (f[i][u]!=f[i][v]) u=f[i][u],v=f[i][v];
    return f[0][u];
}

il void topsort(){
    RG int h=0,t=1; q[t]=S;
    while (h<t){
	RG int x=q[++h],v;
	for (RG int i=head1[x];i;i=g1[i].nt){
	    v=g1[i].to,d[v]--;
	    if (!d[v]){
		q[++t]=v; RG int Lca=0;
		for (RG int j=head2[v];j;j=g2[j].nt)
		    if (!Lca) Lca=g2[j].to; else Lca=lca(Lca,g2[j].to);
		insert(Lca,v,0),f[0][v]=Lca,dep[v]=dep[Lca]+1;
		for (RG int j=1;j<=19;++j) f[j][v]=f[j-1][f[j-1][v]];
	    }
	}
    }
    return;
}

il void work(){
    n=gi(),m=gi(),S=gi();
    for (RG int i=1,u,v,w;i<=m;++i){
	u=gi(),v=gi(),w=gi();
	insert(u,v,w),insert(v,u,w);
    }
    spfa(S);
    cnt=2; dfs1(S); memset(head,0,sizeof(head)),num=0;
    topsort(); dfs2(S); printf("%d\n",ans); return;
}

int main(){
    //    File("757F");
    work();
    return 0;
}


//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1LL<<60)
#define M (300010)
#define N (200010)
#define il inline
#define RG register
#define ll long long
//#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)

using namespace std;

struct edge{ int nt,to; ll dis; }g[2*M],g1[2*M],g2[2*M];

int head[N],head1[N],head2[N],q[20*N],d[N],vis[N],dep[N],sz[N],f[22][N],S,n,m,num,num1,num2,ans;
ll dis[N];

il int gi(){
    RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
}

il void insert(RG int from,RG int to,RG ll dis){ g[++num]=(edge){head[from],to,dis},head[from]=num; return; }

il void insert1(RG int from,RG int to){ g1[++num1]=(edge){head1[from],to},head1[from]=num1; return; }

il void insert2(RG int from,RG int to){ g2[++num2]=(edge){head2[from],to},head2[from]=num2; return; }

il void spfa(RG int S){
    for (RG int i=1;i<=n;++i) dis[i]=inf;
    RG int h=0,t=1; dis[S]=0,vis[S]=1,q[t]=S;
    while (h<t){
	RG int x=q[++h];
	for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	    if (dis[v]>dis[x]+g[i].dis){
		dis[v]=dis[x]+g[i].dis;
		if (!vis[v]) vis[v]=1,q[++t]=v;
	    }
	vis[x]=0;
    }
    return;
}

il void dfs1(RG int x){
    vis[x]=1;
    for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	if (dis[v]==dis[x]+g[i].dis){
	    insert1(x,v),insert2(v,x),d[v]++;
	    if (!vis[v]) dfs1(v);
	}
    return;
}

il void dfs2(RG int x){
    sz[x]=1; RG int v;
    for (RG int i=head[x];i;i=g[i].nt)
	v=g[i].to,dfs2(v),sz[x]+=sz[v];
    if (x!=S) ans=max(ans,sz[x]); return;
}

il int lca(RG int u,RG int v){
    if (u==v) return u; if (dep[u]<dep[v]) swap(u,v);
    for (RG int i=20;i>=0;--i)
	if (dep[f[i][u]]>=dep[v]) u=f[i][u];
    if (u==v) return u;
    for (RG int i=20;i>=0;--i)
	if (f[i][u]!=f[i][v]) u=f[i][u],v=f[i][v];
    return f[0][u];
}

il void topsort(){
    RG int h=0,t=1; q[t]=S;
    while (h<t){
	RG int x=q[++h],v;
	for (RG int i=head1[x];i;i=g1[i].nt){
	    v=g1[i].to,d[v]--;
	    if (!d[v]){
		q[++t]=v; RG int Lca=0;
		for (RG int j=head2[v];j;j=g2[j].nt)
		    if (!Lca) Lca=g2[j].to; else Lca=lca(Lca,g2[j].to);
		insert(Lca,v,0),f[0][v]=Lca,dep[v]=dep[Lca]+1;
		for (RG int j=1;j<=20;++j) f[j][v]=f[j-1][f[j-1][v]];
	    }
	}
    }
    return;
}

il void work(){
    n=gi(),m=gi(),S=gi();
    for (RG int i=1,u,v,w;i<=m;++i){
	u=gi(),v=gi(),w=gi();
	insert(u,v,(ll)w),insert(v,u,(ll)w);
    }
    spfa(S); dfs1(S); memset(head,0,sizeof(head)),num=0;
    topsort(); dfs2(S); printf("%d\n",ans); return;
}

int main(){
    //File("757F");
    work();
    return 0;
}


//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1LL<<60)
#define M (300010)
#define N (200010)
#define il inline
#define RG register
#define ll long long
//#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)

using namespace std;

struct edge{ int nt,to; ll dis; }g[2*M],g1[2*M],g2[2*M];

int head[N],head1[N],head2[N],q[20*N],d[N],vis[N],dep[N],sz[N],f[22][N],S,n,m,num,num1,num2,ans;
ll dis[N];

il int gi(){
    RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
}

il void insert(RG int from,RG int to,RG ll dis){ g[++num]=(edge){head[from],to,dis},head[from]=num; return; }

il void insert1(RG int from,RG int to){ g1[++num1]=(edge){head1[from],to},head1[from]=num1; return; }

il void insert2(RG int from,RG int to){ g2[++num2]=(edge){head2[from],to},head2[from]=num2; return; }

il void spfa(RG int S){
    for (RG int i=1;i<=n;++i) dis[i]=inf;
    RG int h=0,t=1; dis[S]=0,vis[S]=1,q[t]=S;
    while (h<t){
	RG int x=q[++h];
	for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	    if (dis[v]>dis[x]+g[i].dis){
		dis[v]=dis[x]+g[i].dis;
		if (!vis[v]) vis[v]=1,q[++t]=v;
	    }
	vis[x]=0;
    }
    return;
}

il void dfs1(RG int x){
    vis[x]=1;
    for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	if (dis[v]==dis[x]+g[i].dis){
	    insert1(x,v),insert2(v,x),d[v]++;
	    if (!vis[v]) dfs1(v);
	}
    return;
}

il void dfs2(RG int x){
    sz[x]=1; RG int v;
    for (RG int i=head[x];i;i=g[i].nt)
	v=g[i].to,dfs2(v),sz[x]+=sz[v];
    if (x!=S && dis[x]<inf) ans=max(ans,sz[x]); return;
}

il int lca(RG int u,RG int v){
    if (u==v) return u; if (dep[u]<dep[v]) swap(u,v);
    for (RG int i=20;i>=0;--i)
	if (dep[f[i][u]]>=dep[v]) u=f[i][u];
    if (u==v) return u;
    for (RG int i=20;i>=0;--i)
	if (f[i][u]!=f[i][v]) u=f[i][u],v=f[i][v];
    return f[0][u];
}

il void topsort(){
    RG int h=0,t=1; q[t]=S,dep[S]=1;
    while (h<t){
	RG int x=q[++h],v;
	for (RG int i=head1[x];i;i=g1[i].nt){
	    v=g1[i].to,d[v]--;
	    if (!d[v]){
		q[++t]=v; RG int Lca=0;
		for (RG int j=head2[v];j;j=g2[j].nt)
		    if (!Lca) Lca=g2[j].to; else Lca=lca(Lca,g2[j].to);
		insert(Lca,v,0),f[0][v]=Lca,dep[v]=dep[Lca]+1;
		for (RG int j=1;j<=20;++j) f[j][v]=f[j-1][f[j-1][v]];
	    }
	}
    }
    return;
}

il void work(){
    n=gi(),m=gi(),S=gi();
    for (RG int i=1,u,v,w;i<=m;++i){
	u=gi(),v=gi(),w=gi();
	insert(u,v,(ll)w),insert(v,u,(ll)w);
    }
    spfa(S); dfs1(S); memset(head,0,sizeof(head)),num=0;
    topsort(); dfs2(S); printf("%d\n",ans); return;
}

int main(){
    //File("757F");
    work();
    return 0;
}


//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1<<30)
#define M (300010)
#define N (200010)
#define il inline
#define RG register
#define ll long long
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)

using namespace std;

struct edge{ int nt,to,dis; }g[2*M],g1[2*M],g2[2*M];

int head[N],head1[N],head2[N],q[20*N],d[N],dis[N],vis[N],dep[N],sz[N],f[22][N],S,n,m,num,num1,num2,cnt,ans;

il int gi(){
    RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
}

il void insert(RG int from,RG int to,RG int dis){ g[++num]=(edge){head[from],to,dis},head[from]=num; return; }

il void insert1(RG int from,RG int to){ g1[++num1]=(edge){head1[from],to},head1[from]=num1; return; }

il void insert2(RG int from,RG int to){ g2[++num2]=(edge){head2[from],to},head2[from]=num2; return; }

il void spfa(RG int S){
    for (RG int i=1;i<=n;++i) dis[i]=inf;
    RG int h=0,t=1; dis[S]=0,vis[S]=1,q[t]=S;
    while (h<t){
	RG int x=q[++h];
	for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	    if (dis[v]>dis[x]+g[i].dis){
		dis[v]=dis[x]+g[i].dis;
		if (!vis[v]) vis[v]=1,q[++t]=v;
	    }
	vis[x]=0;
    }
    return;
}

il void dfs1(RG int x){
    vis[x]=cnt;
    for (RG int i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to)
	if (dis[v]==dis[x]+g[i].dis){
	    insert1(x,v),insert2(v,x),d[v]++;
	    if (vis[v]!=cnt) dfs1(v);
	}
    return;
}

il void dfs2(RG int x){
    sz[x]=1; RG int v;
    for (RG int i=head[x];i;i=g[i].nt){
	v=g[i].to,dfs2(v),sz[x]+=sz[v];
	//printf("edge %d %d\n",x,v);
    }
    if (x!=S && sz[ans]<sz[x]) ans=x; return;
    //if (x!=S) ans=max(ans,sz[x]-1);
}

il int lca(RG int u,RG int v){
    if (u==v) return u; if (dep[u]<dep[v]) swap(u,v);
    for (RG int i=19;i>=0;--i)
	if (dep[f[i][u]]>=dep[v]) u=f[i][u];
    if (u==v) return u;
    for (RG int i=19;i>=0;--i)
	if (f[i][u]!=f[i][v]) u=f[i][u],v=f[i][v];
    return f[0][u];
}

il void topsort(){
    //for (RG int i=1;i<=n;++i)
    //	if (!d[i]) insert1(n+1,i),insert2(i,n+1),d[i]++;
    RG int h=0,t=1; q[t]=S;
    while (h<t){
	RG int x=q[++h],v;
	for (RG int i=head1[x];i;i=g1[i].nt){
	    v=g1[i].to,d[v]--;
	    if (!d[v]){
		q[++t]=v; RG int Lca=0;
		for (RG int j=head2[v];j;j=g2[j].nt)
		    if (!Lca) Lca=g2[j].to; else Lca=lca(Lca,g2[j].to);
		insert(Lca,v,0),f[0][v]=Lca,dep[v]=dep[Lca]+1;
		for (RG int j=1;j<=19;++j) f[j][v]=f[j-1][f[j-1][v]];
	    }
	}
    }
    return;
}

il void work(){
    n=gi(),m=gi(),S=gi();
    for (RG int i=1,u,v,w;i<=m;++i){
	u=gi(),v=gi(),w=gi();
	insert(u,v,w),insert(v,u,w);
    }
    spfa(S);
    cnt=2; dfs1(S); memset(head,0,sizeof(head)),num=0;
    topsort(); dfs2(S); printf("%d\n",ans); return;
}

int main(){
    File("757F");
    work();
    return 0;
}


//Tanuj Khattar
#include<bits/stdc++.h>

using namespace std;

typedef pair<int,int>   II;
typedef vector< II >      VII;
typedef vector<int>     VI;
typedef vector< VI >  VVI;
typedef long long int   LL;

#define PB push_back
#define MP make_pair
#define F first
#define S second
#define SZ(a) (int)(a.size())
#define ALL(a) a.begin(),a.end()
#define SET(a,b) memset(a,b,sizeof(a))

#define si(n) scanf("%d",&n)
#define dout(n) printf("%d\n",n)
#define sll(n) scanf("%I64d",&n)
#define lldout(n) printf("%I64d\n",n)
#define fast_io ios_base::sync_with_stdio(false);cin.tie(NULL)

#define TRACE

#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
  cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
  const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...)
#endif

//FILE *fin = freopen("in","r",stdin);
//FILE *fout = freopen("out","w",stdout);
const int N = int(3e5)+10;
const int M = int(5e5)+10;
const LL INF = LL(1e16);
namespace Dominator{
  VI g[N],tree[N],rg[N],bucket[N];
  int sdom[N],par[N],dom[N],dsu[N],label[N];
  int arr[N],rev[N],T;//1-Based directed graph input
  int Find(int u,int x=0){
    if(u==dsu[u])return x?-1:u;
    int v = Find(dsu[u],x+1);
    if(v<0)return u;
    if(sdom[label[dsu[u]]]<sdom[label[u]])
      label[u] = label[dsu[u]];
    dsu[u] = v;
    return x?v:label[u];
  }
  void Union(int u,int v){ //Add an edge u-->v
    dsu[v]=u;   //yup,its correct :)
  }
  void dfs0(int u){
    T++;arr[u]=T;rev[T]=u;
    label[T]=T;sdom[T]=T;dsu[T]=T;
    for(int i=0;i<SZ(g[u]);i++){
      int w = g[u][i];
      if(!arr[w])dfs0(w),par[arr[w]]=arr[u];
      rg[arr[w]].PB(arr[u]);
    }
  }
  void dfs1(int u,int p,int sub[]){
    sub[u]=1;
    for(auto w:tree[u])
      if(w!=p)
        dfs1(w,u,sub),sub[u]+=sub[w];
  }
  void reset(int n){
    for(int i=1;i<=n;i++){
      g[i].clear();rg[i].clear();tree[i].clear();arr[i]=0;
    }
    T=0;
  }
  void addEdge(int u,int v){
    g[u].PB(v);
  }
  //Build Dominator tree(in main)
  void get(int n,int root,int sub[]){
    dfs0(root);n=T;
    for(int i=n;i>=1;i--){
      for(int j=0;j<SZ(rg[i]);j++)
        sdom[i] = min(sdom[i],sdom[Find(rg[i][j])]);
      if(i>1)bucket[sdom[i]].PB(i);
      for(int j=0;j<SZ(bucket[i]);j++){
        int w = bucket[i][j],v = Find(w);
        if(sdom[v]==sdom[w])dom[w]=sdom[w];
        else dom[w] = dom[v];
      }if(i>1)Union(par[i],i);
    }
    for(int i=2;i<=n;i++){
      tree[rev[i]].PB(rev[dom[i]]);
      tree[rev[dom[i]]].PB(rev[i]);
    }
    dfs1(rev[1],rev[1],sub);
  }//done :)
}
int n,m,s,vis[N],sub[N];
VII g[N];VI P[N];
LL d[N];
int dijkstra(int root){
  for(int i=1;i<=n;i++)d[i]=INF,P[i].clear();
  Dominator::reset(n);d[root]=0;SET(vis,0);
  set<pair<LL,int>> S;S.insert({d[root],root});
  while(!S.empty()){
    int u = S.begin()->S;
    S.erase(S.begin());
    if(vis[u])continue;
    vis[u]=1;
    for(auto w:g[u])
      if(d[u] + w.S < d[w.F]){
        d[w.F] = d[u] + w.S;
        P[w.F].clear();P[w.F].PB(u);
        S.insert({d[w.F],w.F});
      }
      else if(d[u]+w.S==d[w.F])
        P[w.F].PB(u);
  }
  for(int i=1;i<=n;i++)
    for(auto j : P[i])
        Dominator::addEdge(j,i);
  Dominator::get(n,root,sub);
  int mx = 0;
  for(int i=1;i<=n;i++)
    if(i!=root)
      mx = max(mx,sub[i]);
  return mx;
}
int main()
{
  si(n);si(m);si(s);
  for(int i=1;i<=m;i++){
    int u,v,w;
    si(u);si(v);si(w);
    g[u].PB({v,w});
    g[v].PB({u,w});
  }
  dout(dijkstra(s));
  return 0;
}


//Tanuj Khattar
#include<bits/stdc++.h>

using namespace std;

typedef pair<int,int>   II;
typedef vector< II >      VII;
typedef vector<int>     VI;
typedef vector< VI >  VVI;
typedef long long int   LL;

#define PB push_back
#define MP make_pair
#define F first
#define S second
#define SZ(a) (int)(a.size())
#define ALL(a) a.begin(),a.end()
#define SET(a,b) memset(a,b,sizeof(a))

#define si(n) scanf("%d",&n)
#define dout(n) printf("%d\n",n)
#define sll(n) scanf("%I64d",&n)
#define lldout(n) printf("%I64d\n",n)
#define fast_io ios_base::sync_with_stdio(false);cin.tie(NULL)

#define TRACE

#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
  cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
  const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...)
#endif

//FILE *fin = freopen("in","r",stdin);
//FILE *fout = freopen("out","w",stdout);
const int N = int(3e5)+10;
const int M = int(5e5)+10;
const LL INF = LL(1e16);
namespace Dominator{
  VI g[N],tree[N],rg[N],bucket[N];
  int sdom[N],par[N],dom[N],dsu[N],label[N];
  int arr[N],rev[N],T;//1-Based directed graph input
  int Find(int u,int x=0){
    if(u==dsu[u])return x?-1:u;
    int v = Find(dsu[u],x+1);
    if(v<0)return u;
    if(sdom[label[dsu[u]]]<sdom[label[u]])
      label[u] = label[dsu[u]];
    dsu[u] = v;
    return x?v:label[u];
  }
  void Union(int u,int v){ //Add an edge u-->v
    dsu[v]=u;   //yup,its correct :)
  }
  void dfs0(int u){
    T++;arr[u]=T;rev[T]=u;
    label[T]=T;sdom[T]=T;dsu[T]=T;
    for(int i=0;i<SZ(g[u]);i++){
      int w = g[u][i];
      if(!arr[w])dfs0(w),par[arr[w]]=arr[u];
      rg[arr[w]].PB(arr[u]);
    }
  }
  void dfs1(int u,int p,int sub[]){
    sub[u]=1;
    for(auto w:tree[u])
      if(w!=p)
        dfs1(w,u,sub),sub[u]+=sub[w];
  }
  void reset(int n){
    for(int i=1;i<=n;i++){
      g[i].clear();rg[i].clear();tree[i].clear();arr[i]=0;
    }
    T=0;
  }
  void addEdge(int u,int v){
    g[u].PB(v);
  }
  //Build Dominator tree(in main)
  void get(int n,int root,int sub[]){
    dfs0(root);n=T;
    for(int i=n;i>=1;i--){
      for(int j=0;j<SZ(rg[i]);j++)
        sdom[i] = min(sdom[i],sdom[Find(rg[i][j])]);
      if(i>1)bucket[sdom[i]].PB(i);
      for(int j=0;j<SZ(bucket[i]);j++){
        int w = bucket[i][j],v = Find(w);
        if(sdom[v]==sdom[w])dom[w]=sdom[w];
        else dom[w] = v;
      }if(i>1)Union(par[i],i);
    }
    for(int i=2;i<=n;i++){
      if(dom[i]!=sdom[i])dom[i]=dom[dom[i]];
      tree[rev[i]].PB(rev[dom[i]]);
      tree[rev[dom[i]]].PB(rev[i]);
    }
    dfs1(rev[1],rev[1],sub);
  }//done :)
}
int n,m,s,vis[N],sub[N];
VII g[N];VI P[N];
LL d[N];
int dijkstra(int root){
  for(int i=1;i<=n;i++)d[i]=INF,P[i].clear();
  Dominator::reset(n);d[root]=0;SET(vis,0);
  set<pair<LL,int>> S;S.insert({d[root],root});
  while(!S.empty()){
    int u = S.begin()->S;
    S.erase(S.begin());
    if(vis[u])continue;
    vis[u]=1;
    for(auto w:g[u])
      if(d[u] + w.S < d[w.F]){
        d[w.F] = d[u] + w.S;
        P[w.F].clear();P[w.F].PB(u);
        S.insert({d[w.F],w.F});
      }
      else if(d[u]+w.S==d[w.F])
        P[w.F].PB(u);
  }
  for(int i=1;i<=n;i++)
    for(auto j : P[i])
        Dominator::addEdge(j,i);
  Dominator::get(n,root,sub);
  int mx = 0;
  for(int i=1;i<=n;i++)
    if(i!=root)
      mx = max(mx,sub[i]);
  return mx;
}
int main()
{
  si(n);si(m);si(s);
  for(int i=1;i<=m;i++){
    int u,v,w;
    si(u);si(v);si(w);
    g[u].PB({v,w});
    g[v].PB({u,w});
  }
  dout(dijkstra(s));
  return 0;
}


//Tanuj Khattar
#include<bits/stdc++.h>

using namespace std;

typedef pair<int,int>   II;
typedef vector< II >      VII;
typedef vector<int>     VI;
typedef vector< VI >  VVI;
typedef long long int   LL;

#define PB push_back
#define MP make_pair
#define F first
#define S second
#define SZ(a) (int)(a.size())
#define ALL(a) a.begin(),a.end()
#define SET(a,b) memset(a,b,sizeof(a))

#define si(n) scanf("%d",&n)
#define dout(n) printf("%d\n",n)
#define sll(n) scanf("%I64d",&n)
#define lldout(n) printf("%I64d\n",n)
#define fast_io ios_base::sync_with_stdio(false);cin.tie(NULL)

#define TRACE

#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
  cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
  const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...)
#endif

//FILE *fin = freopen("in","r",stdin);
//FILE *fout = freopen("out","w",stdout);
const int N = int(3e5)+10;
const int M = int(5e5)+10;
const LL INF = LL(1e16);
namespace Dominator{
  VI g[N],tree[N],rg[N],bucket[N];
  int sdom[N],par[N],dom[N],dsu[N],label[N];
  int arr[N],rev[N],T;//1-Based directed graph input
  int Find(int u,int x=0){
    if(u==dsu[u])return x?-1:u;
    int v = Find(dsu[u],x+1);
    if(v<0)return u;
    if(sdom[label[dsu[u]]]<sdom[label[u]])
      label[u] = label[dsu[u]];
    dsu[u] = v;
    return x?v:label[u];
  }
  void Union(int u,int v){ //Add an edge u-->v
    dsu[v]=u;   //yup,its correct :)
  }
  void dfs0(int u){
    T++;arr[u]=T;rev[T]=u;
    label[T]=T;sdom[T]=T;dsu[T]=T;
    for(int i=0;i<SZ(g[u]);i++){
      int w = g[u][i];
      if(!arr[w])dfs0(w),par[arr[w]]=arr[u];
      rg[arr[w]].PB(arr[u]);
    }
  }
  void dfs1(int u,int p,int sub[]){
    sub[u]=1;
    for(auto w:tree[u])
      if(w!=p)
        dfs1(w,u,sub),sub[u]+=sub[w];
  }
  void reset(int n){
    for(int i=1;i<=n;i++){
      g[i].clear();rg[i].clear();tree[i].clear();arr[i]=0;
    }
    T=0;
  }
  void addEdge(int u,int v){
    g[u].PB(v);
  }
  //Build Dominator tree(in main)
  void get(int n,int root,int sub[]){
    dfs0(root);n=T;
    for(int i=n;i>=1;i--){
      for(int j=0;j<SZ(rg[i]);j++)
        sdom[i] = min(sdom[i],sdom[Find(rg[i][j])]);
      if(i>1)bucket[sdom[i]].PB(i);
      for(int j=0;j<SZ(bucket[i]);j++){
        int w = bucket[i][j],v = Find(w);
        if(sdom[v]==sdom[w] || v==sdom[w])dom[w]=sdom[w];
        else dom[w] = dom[v];
      }if(i>1)Union(par[i],i);
    }
    for(int i=2;i<=n;i++){
      tree[rev[i]].PB(rev[dom[i]]);
      tree[rev[dom[i]]].PB(rev[i]);
    }
    dfs1(rev[1],rev[1],sub);
  }//done :)
}
int n,m,s,vis[N],sub[N];
VII g[N];VI P[N];
LL d[N];
int dijkstra(int root){
  for(int i=1;i<=n;i++)d[i]=INF,P[i].clear();
  Dominator::reset(n);d[root]=0;SET(vis,0);
  set<pair<LL,int>> S;S.insert({d[root],root});
  while(!S.empty()){
    int u = S.begin()->S;
    S.erase(S.begin());
    if(vis[u])continue;
    vis[u]=1;
    for(auto w:g[u])
      if(d[u] + w.S < d[w.F]){
        d[w.F] = d[u] + w.S;
        P[w.F].clear();P[w.F].PB(u);
        S.insert({d[w.F],w.F});
      }
      else if(d[u]+w.S==d[w.F])
        P[w.F].PB(u);
  }
  for(int i=1;i<=n;i++)
    for(auto j : P[i])
        Dominator::addEdge(j,i);
  Dominator::get(n,root,sub);
  int mx = 0;
  for(int i=1;i<=n;i++)
    if(i!=root)
      mx = max(mx,sub[i]);
  return mx;
}
int main()
{
  si(n);si(m);si(s);
  for(int i=1;i<=m;i++){
    int u,v,w;
    si(u);si(v);si(w);
    g[u].PB({v,w});
    g[v].PB({u,w});
  }
  dout(dijkstra(s));
  return 0;
}


//Tanuj Khattar
#include<bits/stdc++.h>

using namespace std;

typedef pair<int,int>   II;
typedef vector< II >      VII;
typedef vector<int>     VI;
typedef vector< VI >  VVI;
typedef long long int   LL;

#define PB push_back
#define MP make_pair
#define F first
#define S second
#define SZ(a) (int)(a.size())
#define ALL(a) a.begin(),a.end()
#define SET(a,b) memset(a,b,sizeof(a))

#define si(n) scanf("%d",&n)
#define dout(n) printf("%d\n",n)
#define sll(n) scanf("%I64d",&n)
#define lldout(n) printf("%I64d\n",n)
#define fast_io ios_base::sync_with_stdio(false);cin.tie(NULL)

#define TRACE

#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
  cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
  const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...)
#endif

//FILE *fin = freopen("in","r",stdin);
//FILE *fout = freopen("out","w",stdout);
const int N = int(3e5)+10;
const int M = int(5e5)+10;
const LL INF = LL(1e16);
namespace Dominator{
  VI g[N],tree[N],rg[N],bucket[N];
  int sdom[N],par[N],dom[N],dsu[N],label[N];
  int arr[N],rev[N],T;//1-Based directed graph input
  int Find(int u,int x=0){
    if(u==dsu[u])return x?-1:u;
    int v = Find(dsu[u],x+1);
    if(v<0)return u;
    if(sdom[label[dsu[u]]]<sdom[label[u]])
      label[u] = label[dsu[u]];
    dsu[u] = v;
    return x?v:label[u];
  }
  void Union(int u,int v){ //Add an edge u-->v
    dsu[v]=u;   //yup,its correct :)
  }
  void dfs0(int u){
    T++;arr[u]=T;rev[T]=u;
    label[T]=T;sdom[T]=T;dsu[T]=T;
    for(int i=0;i<SZ(g[u]);i++){
      int w = g[u][i];
      if(!arr[w])dfs0(w),par[arr[w]]=arr[u];
      rg[arr[w]].PB(arr[u]);
    }
  }
  void dfs1(int u,int p,int sub[]){
    sub[u]=1;
    for(auto w:tree[u])
      if(w!=p)
        dfs1(w,u,sub),sub[u]+=sub[w];
  }
  void reset(int n){
    for(int i=1;i<=n;i++){
      g[i].clear();rg[i].clear();tree[i].clear();arr[i]=0;
    }
    T=0;
  }
  void addEdge(int u,int v){
    g[u].PB(v);
  }
  //Build Dominator tree(in main)
  void get(int n,int root,int sub[]){
    dfs0(root);n=T;
    for(int i=n;i>=1;i--){
      for(int j=0;j<SZ(rg[i]);j++)
        sdom[i] = min(sdom[i],sdom[Find(rg[i][j])]);
      if(i>1)bucket[sdom[i]].PB(i);
      for(int j=0;j<SZ(bucket[i]);j++){
        int w = bucket[i][j],v = Find(w);
        if(sdom[v]==sdom[w])dom[w]=sdom[w];
        else dom[w] = dom[v];
      }if(i>1)Union(par[i],i);
    }
    for(int i=2;i<=n;i++){
      if(dom[i]!=sdom[i])dom[i]=dom[dom[i]];
      tree[rev[i]].PB(rev[dom[i]]);
      tree[rev[dom[i]]].PB(rev[i]);
    }
    dfs1(rev[1],rev[1],sub);
  }//done :)
}
int n,m,s,vis[N],sub[N];
VII g[N];VI P[N];
LL d[N];
int dijkstra(int root){
  for(int i=1;i<=n;i++)d[i]=INF,P[i].clear();
  Dominator::reset(n);d[root]=0;SET(vis,0);
  set<pair<LL,int>> S;S.insert({d[root],root});
  while(!S.empty()){
    int u = S.begin()->S;
    S.erase(S.begin());
    if(vis[u])continue;
    vis[u]=1;
    for(auto w:g[u])
      if(d[u] + w.S < d[w.F]){
        d[w.F] = d[u] + w.S;
        P[w.F].clear();P[w.F].PB(u);
        S.insert({d[w.F],w.F});
      }
      else if(d[u]+w.S==d[w.F])
        P[w.F].PB(u);
  }
  for(int i=1;i<=n;i++)
    for(auto j : P[i])
        Dominator::addEdge(j,i);
  Dominator::get(n,root,sub);
  int mx = 0;
  for(int i=1;i<=n;i++)
    if(i!=root)
      mx = max(mx,sub[i]);
  return mx;
}
int main()
{
  si(n);si(m);si(s);
  for(int i=1;i<=m;i++){
    int u,v,w;
    si(u);si(v);si(w);
    g[u].PB({v,w});
    g[v].PB({u,w});
  }
  dout(dijkstra(s));
  return 0;
}


//Tanuj Khattar
#include<bits/stdc++.h>

using namespace std;

typedef pair<int,int>   II;
typedef vector< II >      VII;
typedef vector<int>     VI;
typedef vector< VI >  VVI;
typedef long long int   LL;

#define PB push_back
#define MP make_pair
#define F first
#define S second
#define SZ(a) (int)(a.size())
#define ALL(a) a.begin(),a.end()
#define SET(a,b) memset(a,b,sizeof(a))

#define si(n) scanf("%d",&n)
#define dout(n) printf("%d\n",n)
#define sll(n) scanf("%I64d",&n)
#define lldout(n) printf("%lld\n",n)
#define fast_io ios_base::sync_with_stdio(false);cin.tie(NULL)

#define TRACE

#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
  cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
  const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...)
#endif

//FILE *fin = freopen("in","r",stdin);
//FILE *fout = freopen("out","w",stdout);
const int N = int(1e5)+10;
const int M = int(2e5)+10;
const LL INF = LL(1e16);
namespace Dominator{
  VI g[N],tree[N],rg[N],bucket[N];
  int sdom[N],par[N],dom[N],dsu[N],label[N];
  int arr[N],rev[N],T;//1-Based directed graph input
  int Find(int u,int x=0){
    if(u==dsu[u])return x?-1:u;
    int v = Find(dsu[u],x+1);
    if(v<0)return u;
    if(sdom[label[dsu[u]]]<sdom[label[u]])
      label[u] = label[dsu[u]];
    dsu[u] = v;
    return x?v:label[u];
  }
  void Union(int u,int v){ //Add an edge u-->v
    dsu[v]=u;   //yup,its correct :)
  }
  void dfs0(int u){
    T++;arr[u]=T;rev[T]=u;
    label[T]=T;sdom[T]=T;dsu[T]=T;
    for(int i=0;i<SZ(g[u]);i++){
      int w = g[u][i];
      if(!arr[w])dfs0(w),par[arr[w]]=arr[u];
      rg[arr[w]].PB(arr[u]);
    }
  }
  void dfs1(int u,int p,int sub[]){
    sub[u]=1;
    for(auto w:tree[u])
      if(w!=p)
        dfs1(w,u,sub),sub[u]+=sub[w];
  }
  void reset(int n){
    for(int i=1;i<=n;i++){
      g[i].clear();rg[i].clear();tree[i].clear();arr[i]=0;
    }
    T=0;
  }
  void addEdge(int u,int v){
    g[u].PB(v);
  }
  //Build Dominator tree(in main)
  void get(int n,int root,int sub[]){
    dfs0(root);n=T;
    for(int i=n;i>=1;i--){
      for(int j=0;j<SZ(rg[i]);j++)
        sdom[i] = min(sdom[i],sdom[Find(rg[i][j])]);
      if(i>1)bucket[sdom[i]].PB(i);
      for(int j=0;j<SZ(bucket[i]);j++){
        int w = bucket[i][j],v = Find(w);
        if(sdom[v]==sdom[w])dom[w]=sdom[w];
        else dom[w] = dom[v];
      }if(i>1)Union(par[i],i);
    }
    for(int i=2;i<=n;i++){
      if(dom[i]!=sdom[i])dom[i]=dom[dom[i]];
      tree[rev[i]].PB(rev[dom[i]]);
      tree[rev[dom[i]]].PB(rev[i]);
    }
    dfs1(rev[1],rev[1],sub);
  }//done :)
}
int n,m,s,vis[N],sub[N];
VII g[N];VI P[N];
LL d[N];
int dijkstra(int root){
  for(int i=1;i<=n;i++)d[i]=INF,P[i].clear();
  Dominator::reset(n);d[root]=0;SET(vis,0);
  set<pair<LL,int>> S;S.insert({d[root],root});
  while(!S.empty()){
    int u = S.begin()->S;
    S.erase(S.begin());
    if(vis[u])continue;
    vis[u]=1;
    for(auto w:g[u])
      if(d[u] + w.S < d[w.F]){
        d[w.F] = d[u] + w.S;
        P[w.F].clear();P[w.F].PB(u);
        S.insert({d[w.F],w.F});
      }
      else if(d[u]+w.S==d[w.F])
        P[w.F].PB(u);
  }
  for(int i=1;i<=n;i++)
    for(auto j : P[i])
        Dominator::addEdge(j,i);
  Dominator::get(n,root,sub);
  int mx = 0;
  for(int i=1;i<=n;i++)
    if(i!=root)
      mx = max(mx,sub[i]);
  return mx;
}
int main()
{
  si(n);si(m);si(s);
  for(int i=1;i<=m;i++){
    int u,v,w;
    si(u);si(v);si(w);
    g[u].PB({v,w});
    g[v].PB({u,w});
  }
  dout(dijkstra(s));
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 200005;
typedef pair <int, int> pii;
typedef pair <pii, int> piii;
int n, m, s;
vector <pii> edges [MAXN];
int vis [MAXN];
int dist[MAXN];
vector <int> ded [MAXN];
vector <int> rev_ded[MAXN];
vector <int> df_tree [MAXN];
vector <int> dom_tree [MAXN];
int depth[MAXN];
int pa [MAXN][20];
int mini[MAXN][20];
void go (int node){
    priority_queue <pii, vector<pii>, greater <pii> > pq;
    pq.push(pii(0, node));
    while (pq.size()){
        pii xd = pq.top(); pq.pop();
        int no = xd.second, di = xd.first;
        if (vis[no]) continue;
        vis[no]=1;
        dist[no]=di;
        for (pii i : edges[no]){
            if(vis[i.first])continue;
            pq.push(pii(di+i.second,i.first));
        }
    }
}
void dfs (int node, int p=0){
    vis[node]=1;
    if(p!=0)depth[node]=depth[p]+1;
    pa[node][0]=p;
    for (int i:ded[node]){
        if(vis[i])continue;
        dfs(i,node);
        df_tree[node].push_back(i);
    }
}
int get_mi (int a, int b){
    int ans = 1e9;
    for (int i=19;i>=0;i--){
        if((1<<i)&b){
            ans=min(ans,mini[a][i]);
            a=pa[a][i];
        }
    }
    return ans;
}
int get_up (int a, int b){
    for (int i=19; i>=0; i--){
        if((1<<i)&b)a=pa[a][i];
    }
    return a;
}
int lca(int a, int b){
    if(depth[a]>depth[b])swap(a,b);
    int zk = depth[b]-depth[a];
    for(int i=19;i>=0;i--){
        if ((1<<i)&zk)b=pa[b][i];
    }
    if(a==b) return a;
    for (int i=19; i>=0; i--){
        if (pa[a][i]!=pa[b][i])a=pa[a][i],b=pa[b][i];
    }
    return pa[a][0];
}
void sol (int node, int p=0){
    if(p==0){
        for(int i:df_tree[node]){
            if (i==p)continue;
            sol(i, node);
        }
        return;
    }
    int miz=depth[node]-1;
    for (int i:rev_ded[node]){
        if(i!=pa[node][0]){
            miz=min(miz,depth[lca(i,node)]);
        }
    }
    int mi_val = min(miz,get_mi(pa[node][0],depth[pa[node][0]]-miz));
    int up_no = get_up(node, depth[node]-mi_val);
    dom_tree[up_no].push_back(node);
    mini[node][0]=mi_val;
    for (int i=1;i<=19;i++){
        mini[node][i]=min(mini[node][i-1], mini[pa[node][i-1]][i-1]);
    }
    for(int i:df_tree[node]){
        if (i==p)continue;
        sol(i, node);
    }
}
int answ=0;
int su (int node, int p=0){
    int tot=1;
    for (int i:dom_tree[node]){
        if(i==p)continue;
        tot+=su(i,node);
    }
    if(p!=0)answ=max(answ,tot);
    return tot;
}
main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> m >> s;
    for (int i=0; i<m; i++){
        int a, b, c; cin >> a >> b >> c;
        edges[a].push_back(pii(b, c));
        edges[b].push_back(pii(a, c));
    }
    go(s);
    for (int i=1; i<=n; i++){
        if(!vis[i])continue;
        for (pii j : edges[i]){
            if (dist[j.first] + j.second == dist[i]) {
                ded[j.first].push_back(i);
                rev_ded[i].push_back(j.first);
            }
        }
    }
    memset(vis,0,sizeof(vis));
    dfs (s);
    for (int i=1; i<=19; i++) for (int j=1; j<=n; j++){
        pa[j][i]=pa[pa[j][i-1]][i-1];
    }
    for (int i=0; i<=n; i++) for (int j=0; j<=19; j++) mini[i][j]=1e9;
    sol (s);
    su(s);
    cout<<answ<<'\n';
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 200005;
typedef pair <int, int> pii;
typedef pair <pii, int> piii;
int n, m, s;
vector <pii> edges [MAXN];
int vis [MAXN];
int dist[MAXN];
vector <int> ded [MAXN];
vector <int> rev_ded[MAXN];
vector <int> df_tree [MAXN];
vector <int> dom_tree [MAXN];
int depth[MAXN];
int pa [MAXN][20];
int mini[MAXN][20];
void go (int node){
    priority_queue <pii, vector<pii>, greater <pii> > pq;
    pq.push(pii(0, node));
    while (pq.size()){
        pii xd = pq.top(); pq.pop();
        int no = xd.second, di = xd.first;
        if (vis[no]) continue;
        vis[no]=1;
        dist[no]=di;
        for (pii i : edges[no]){
            if(vis[i.first])continue;
            pq.push(pii(di+i.second,i.first));
        }
    }
}
void dfs (int node){
    vis[node]=1;
    for (int i:ded[node]){
        if(vis[i])continue;
        dfs(i);
        df_tree[node].push_back(i);
        pa[i][0]=node;
        depth[i]=depth[node]+1;
    }
}
int get_mi (int a, int b){
    int ans = 1e9;
    for (int i=19;i>=0;i--){
        if((1<<i)&b){
            ans=min(ans,mini[a][i]);
            a=pa[a][i];
        }
    }
    return ans;
}
int get_up (int a, int b){
    for (int i=19; i>=0; i--){
        if((1<<i)&b)a=pa[a][i];
    }
    return a;
}
int lca(int a, int b){
    if(depth[a]>depth[b])swap(a,b);
    int zk = depth[b]-depth[a];
    for(int i=19;i>=0;i--){
        if ((1<<i)&zk)b=pa[b][i];
    }
    if(a==b) return a;
    for (int i=19; i>=0; i--){
        if (pa[a][i]!=pa[b][i])a=pa[a][i],b=pa[b][i];
    }
    return pa[a][0];
}
void sol (int node, int p=0){
    if(p==0){
        for(int i:df_tree[node]){
            if (i==p)continue;
            sol(i, node);
        }
        return;
    }
    int miz=depth[node]-1;
    for (int i:rev_ded[node]){
        if(i!=pa[node][0]){
            miz=min(miz,depth[lca(i,node)]);
        }
    }
    int mi_val = min(miz,get_mi(pa[node][0],depth[pa[node][0]]-miz));
    int up_no = get_up(node, depth[node]-mi_val);
    dom_tree[up_no].push_back(node);
    mini[node][0]=mi_val;
    for (int i=1;i<=19;i++){
        mini[node][i]=min(mini[node][i-1], mini[pa[node][i-1]][i-1]);
    }
    for(int i:df_tree[node]){
        if (i==p)continue;
        sol(i, node);
    }
}
int answ=0;
int su (int node, int p=0){
    int tot=1;
    for (int i:dom_tree[node]){
        if(i==p)continue;
        tot+=su(i,node);
    }
    if(p!=0)answ=max(answ,tot);
    return tot;
}
main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> m >> s;
    for (int i=0; i<m; i++){
        int a, b, c; cin >> a >> b >> c;
        edges[a].push_back(pii(b, c));
        edges[b].push_back(pii(a, c));
    }
    go(s);
    for (int i=1; i<=n; i++){
        if(!vis[i])continue;
        for (pii j : edges[i]){
            if (dist[j.first] + j.second == dist[i]) {ded[j.first].push_back(i); rev_ded[i].push_back(j.first);}
        }
    }
    memset(vis,0,sizeof(vis));
    dfs (s);
    for (int i=1; i<=19; i++) for (int j=1; j<=n; j++){
        pa[j][i]=pa[pa[j][i-1]][i-1];
    }
    for (int i=1; i<=n; i++) for (int j=0; j<=19; j++) mini[i][j]=1e9;
    sol (s);
    su(s);
    cout<<answ<<'\n';
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 200005;
typedef pair <int, int> pii;
typedef pair <pii, int> piii;
int n, m, s;
vector <pii> edges [MAXN];
int vis [MAXN];
int dist[MAXN];
vector <int> ded [MAXN];
vector <int> rev_ded[MAXN];
vector <int> df_tree [MAXN];
vector <int> dom_tree [MAXN];
int depth[MAXN];
int pa [MAXN][20];
int dom_pa[MAXN][20];
void go (int node){
    priority_queue <pii, vector<pii>, greater <pii> > pq;
    pq.push(pii(0, node));
    while (pq.size()){
        pii xd = pq.top(); pq.pop();
        int no = xd.second, di = xd.first;
        if (vis[no]) continue;
        vis[no]=1;
        dist[no]=di;
        for (pii i : edges[no]){
            if(vis[i.first])continue;
            pq.push(pii(di+i.second,i.first));
        }
    }
}
void dfs (int node, int p=0){
    vis[node]=1;
    if(p!=0)depth[node]=depth[p]+1;
    pa[node][0]=p;
    for (int i:ded[node]){
        if(vis[i])continue;
        dfs(i,node);
        df_tree[node].push_back(i);
    }
}
int lca(int a, int b){
    if(depth[a]>depth[b])swap(a,b);
    int zk = depth[b]-depth[a];
    for(int i=19;i>=0;i--){
        if ((1<<i)&zk)b=dom_pa[b][i];
    }
    if(a==b) return a;
    for (int i=19; i>=0; i--){
        if (dom_pa[a][i]!=dom_pa[b][i])a=dom_pa[a][i],b=dom_pa[b][i];
    }
    return dom_pa[a][0];
}
int answ=0;
int su (int node, int p=0){
    int tot=1;
    for (int i:dom_tree[node]){
        if(i==p)continue;
        tot+=su(i,node);
    }
    if(p!=0)answ=max(answ,tot);
    return tot;
}
bool cmp(int a, int b){
    return dist[a]<dist[b];
}
main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> m >> s;
    for (int i=0; i<m; i++){
        int a, b, c; cin >> a >> b >> c;
        edges[a].push_back(pii(b, c));
        edges[b].push_back(pii(a, c));
    }
    go(s);
    vector <int> xd;
    for (int i=1; i<=n; i++){
        if(!vis[i])continue;
        xd.push_back(i);
        for (pii j : edges[i]){
            if (dist[j.first] + j.second == dist[i]) {
                ded[j.first].push_back(i);
                rev_ded[i].push_back(j.first);
            }
        }
    }
    sort(xd.begin(),xd.end(),cmp);
    memset(vis,0,sizeof(vis));
    dfs (s);
    for (int i=1; i<=19; i++) for (int j=1; j<=n; j++){
        pa[j][i]=pa[pa[j][i-1]][i-1];
    }
    for (int node:xd){
        if(node==s)continue;
        int no = -1;
        for (int i:rev_ded[node]){
            if(dist[i] < dist[node]){
                if(no==-1)no=i;
                else no=lca(no,i);
            }
        }
        dom_tree[no].push_back(node);
        dom_pa[node][0]=no;
        for (int i=1;i<=19;i++){
            dom_pa[node][i]=dom_pa[dom_pa[node][i-1]][i-1];
        }
    }
    su(s);
    cout<<answ<<'\n';
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200005;
typedef pair <int, int> pii;
typedef pair <pii, int> piii;
int n, m, s;
vector <pii> edges [MAXN];
int vis [MAXN];
int dist[MAXN];
vector <int> ded [MAXN];
vector <int> df_tree [MAXN];
vector <int> dom_tree [MAXN];
int depth[MAXN];
int pa [MAXN][20];
int mini[MAXN][20];
void go (int node){
    priority_queue <pii, vector<pii>, greater <pii> > pq;
    pq.push(pii(0, node));
    while (pq.size()){
        pii xd = pq.top(); pq.pop();
        int no = xd.second, di = xd.first;
        if (vis[no]) continue;
        vis[no]=1;
        dist[no]=di;
        for (pii i : edges[no]){
            if(vis[i.first])continue;
            pq.push(pii(di+i.second,i.first));
        }
    }
}
void dfs (int node){
    vis[node]=1;
    for (int i:ded[node]){
        if(vis[i])continue;
        dfs(i);
        df_tree[node].push_back(i);
        pa[i][0]=node;
        depth[i]=depth[node]+1;
    }
}
int get_mi (int a, int b){
    int ans = 1e9;
    for (int i=19;i>=0;i--){
        if((1<<i)&b){
            ans=min(ans,mini[a][i]);
            a=pa[a][i];
        }
    }
    return ans;
}
int get_up (int a, int b){
    for (int i=19; i>=0; i--){
        if((1<<i)&b)a=pa[a][i];
    }
    return a;
}
void sol (int node, int p=0){
    if(p==0){
        for(int i:df_tree[node]){
            if (i==p)continue;
            sol(i, node);
        }
        return;
    }
    int miz=depth[node]-1;
    for (int i:ded[node]){
        if(depth[i]<depth[node])miz=min(miz,depth[i]);
    }
    int mi_val = min(miz,get_mi(pa[node][0],depth[pa[node][0]]-miz));
    int up_no = get_up(node, depth[node]-mi_val);
    dom_tree[up_no].push_back(node);
    mini[node][0]=mi_val;
    for (int i=1;i<=19;i++){
        mini[node][i]=min(mini[node][i-1], mini[pa[node][i-1]][i-1]);
    }
    for(int i:df_tree[node]){
        if (i==p)continue;
        sol(i, node);
    }
}
int answ=0;
int su (int node, int p=0){
    int tot=1;
    for (int i:dom_tree[node]){
        if(i==p)continue;
        tot+=su(i,node);
    }
    if(p!=0)answ=max(answ,tot);
    return tot;
}
int main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> m >> s;
    for (int i=0; i<m; i++){
        int a, b, c; cin >> a >> b >> c;
        edges[a].push_back(pii(b, c));
        edges[b].push_back(pii(a, c));
    }
    go(s);
    for (int i=1; i<=n; i++){
        if(!vis[i])continue;
        for (pii j : edges[i]){
            if (dist[j.first] + j.second == dist[i]) ded[j.first].push_back(i);
        }
    }
    memset(vis,0,sizeof(vis));
    dfs (s);
    for (int i=1; i<=19; i++) for (int j=1; j<=n; j++){
        pa[j][i]=pa[pa[j][i-1]][i-1];
    }
    for (int i=1; i<=n; i++) for (int j=0; j<=19; j++) mini[i][j]=1e9;
    sol (s);
    su(s);
    cout<<answ<<'\n';
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 200005;
typedef pair <int, int> pii;
typedef pair <pii, int> piii;
int n, m, s;
vector <pii> edges [MAXN];
int vis [MAXN];
int dist[MAXN];
vector <int> ded [MAXN];
vector <int> rev_ded[MAXN];
vector <int> df_tree [MAXN];
vector <int> dom_tree [MAXN];
int dom_depth[MAXN];
int depth[MAXN];
int pa [MAXN][20];
int dom_pa[MAXN][20];
void go (int node){
    priority_queue <pii, vector<pii>, greater <pii> > pq;
    pq.push(pii(0, node));
    while (pq.size()){
        pii xd = pq.top(); pq.pop();
        int no = xd.second, di = xd.first;
        if (vis[no]) continue;
        vis[no]=1;
        dist[no]=di;
        for (pii i : edges[no]){
            if(vis[i.first])continue;
            pq.push(pii(di+i.second,i.first));
        }
    }
}
void dfs (int node, int p=0){
    vis[node]=1;
    if(p!=0)depth[node]=depth[p]+1;
    pa[node][0]=p;
    for (int i:ded[node]){
        if(vis[i])continue;
        dfs(i,node);
        df_tree[node].push_back(i);
    }
}
int lca(int a, int b){
    if(dom_depth[a]>dom_depth[b])swap(a,b);
    int zk = dom_depth[b]-dom_depth[a];
    for(int i=19;i>=0;i--){
        if ((1<<i)&zk)b=dom_pa[b][i];
    }
    if(a==b) return a;
    for (int i=19; i>=0; i--){
        if (dom_pa[a][i]!=dom_pa[b][i])a=dom_pa[a][i],b=dom_pa[b][i];
    }
    return dom_pa[a][0];
}
int answ=0;
int su (int node, int p=0){
    int tot=1;
    for (int i:dom_tree[node]){
        if(i==p)continue;
        tot+=su(i,node);
    }
    if(p!=0)answ=max(answ,tot);
    return tot;
}
bool cmp(int a, int b){
    return dist[a]<dist[b];
}
main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> m >> s;
    for (int i=0; i<m; i++){
        int a, b, c; cin >> a >> b >> c;
        edges[a].push_back(pii(b, c));
        edges[b].push_back(pii(a, c));
    }
    go(s);
    vector <int> xd;
    for (int i=1; i<=n; i++){
        if(!vis[i])continue;
        xd.push_back(i);
        for (pii j : edges[i]){
            if (dist[j.first] + j.second == dist[i]) {
                ded[j.first].push_back(i);
                rev_ded[i].push_back(j.first);
            }
        }
    }
    sort(xd.begin(),xd.end(),cmp);
    memset(vis,0,sizeof(vis));
    dfs (s);
    for (int i=1; i<=19; i++) for (int j=1; j<=n; j++){
        pa[j][i]=pa[pa[j][i-1]][i-1];
    }
    for (int node:xd){
        if(node==s)continue;
        int no = -1;
        for (int i:rev_ded[node]){
            if(dist[i] < dist[node]){
                if(no==-1) no=i;
                else no=lca(no,i);
            }
        }
        dom_tree[no].push_back(node);
        dom_pa[node][0]=no;
        dom_depth[node]=dom_depth[no]+1;
        for (int i=1;i<=19;i++){
            dom_pa[node][i]=dom_pa[dom_pa[node][i-1]][i-1];
        }
    }
    su(s);
    cout<<answ<<'\n';
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 200005;
typedef pair <int, int> pii;
typedef pair <pii, int> piii;
int n, m, s;
vector <pii> edges [MAXN];
int vis [MAXN];
int dist[MAXN];
vector <int> ded [MAXN];
vector <int> rev_ded[MAXN];
vector <int> df_tree [MAXN];
vector <int> dom_tree [MAXN];
int dom_depth[MAXN];
int depth[MAXN];
int pa [MAXN][20];
int dom_pa[MAXN][20];
void go (int node){
    priority_queue <pii, vector<pii>, greater <pii> > pq;
    pq.push(pii(0, node));
    while (pq.size()){
        pii xd = pq.top(); pq.pop();
        int no = xd.second, di = xd.first;
        if (vis[no]) continue;
        vis[no]=1;
        dist[no]=di;
        for (pii i : edges[no]){
            if(vis[i.first])continue;
            pq.push(pii(di+i.second,i.first));
        }
    }
}
void dfs (int node, int p=0){
    vis[node]=1;
    if(p!=0)depth[node]=depth[p]+1;
    pa[node][0]=p;
    for (int i:ded[node]){
        if(vis[i])continue;
        dfs(i,node);
        df_tree[node].push_back(i);
    }
}
int lca(int a, int b){
    if(dom_depth[a]>dom_depth[b])swap(a,b);
    int zk = dom_depth[b]-dom_depth[a];
    for(int i=19;i>=0;i--){
        if ((1<<i)&zk)b=dom_pa[b][i];
    }
    if(a==b) return a;
    for (int i=19; i>=0; i--){
        if (dom_pa[a][i]!=dom_pa[b][i])a=dom_pa[a][i],b=dom_pa[b][i];
    }
    return dom_pa[a][0];
}
int answ=0;
int su (int node, int p=0){
    int tot=1;
    for (int i:dom_tree[node]){
        if(i==p)continue;
        tot+=su(i,node);
    }
    if(p!=0)answ=max(answ,tot);
    return tot;
}
bool cmp(int a, int b){
    return dist[a]<dist[b];
}
main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> m >> s;
    for (int i=0; i<m; i++){
        int a, b, c; cin >> a >> b >> c;
        edges[a].push_back(pii(b, c));
        edges[b].push_back(pii(a, c));
    }
    go(s);
    vector <int> xd;
    for (int i=1; i<=n; i++){
        if(!vis[i])continue;
        xd.push_back(i);
        for (pii j : edges[i]){
            if (dist[j.first] + j.second == dist[i]) {
                ded[j.first].push_back(i);
                rev_ded[i].push_back(j.first);
            }
        }
    }
    sort(xd.begin(),xd.end(),cmp);
    memset(vis,0,sizeof(vis));
    dfs (s);
    for (int i=1; i<=19; i++) for (int j=1; j<=n; j++){
        pa[j][i]=pa[pa[j][i-1]][i-1];
    }
    for (int node:xd){
        if(node==s)continue;
        int no = pa[node][0];
        for (int i:rev_ded[node]){
            if(dist[i] < dist[node]){
                no=lca(no,i);
            }
        }
        dom_tree[no].push_back(node);
        dom_pa[node][0]=no;
        dom_depth[node]=dom_depth[no]+1;
        for (int i=1;i<=19;i++){
            dom_pa[node][i]=dom_pa[dom_pa[node][i-1]][i-1];
        }
    }
    su(s);
    cout<<answ<<'\n';
    return 0;
}