#include <iostream>
#include <algorithm>

using namespace std;

struct pt{
	int a, b;
	bool operator < (pt a2)
	{
		return b < a2.b || (b == a2.b && a < a2.a);
	}
};
int main()
{
	pt marker[10000], cap[10000];
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; i++)
		cin >> marker[i].a >> marker[i].b;
	sort(marker, marker + n);
	for (int i = 0; i < m; i++)
		cin >> cap[i].a >> cap[i].b;
	sort(cap, cap + m);
	int i = 0, j = 0, closed = 0, beautiful = 0;
	while(i < n && j < m)
	{
		if (marker[i].b < cap[j].b)
		{
			i++;
			continue;
		}
		if (cap[j].b < marker[i].b)
		{
			j++;
			continue;
		}
		closed++;
		if (cap[j].a == marker[i].a)
			beautiful++;
		else if (cap[j + 1].b == cap[j].b)
			j--;
		i++, j++;
	}
	cout << closed << " " << beautiful << endl;

}


#include <iostream>

using namespace std;

int Checked[1010][1010] = {0};
int Num[1010] = {0}, Rem[1010] = {0};

int main()
{
	int n, m, closed = 0, beautiful = 0;
	cin >> n >> m;
	for (int i = 0; i < n; i++)
	{
		int a, b;
		cin >> a >> b;
		Num[b]++;
		Checked[b][a]++;
	}
	for (int i = 0; i < m; i++)
	{
		int x, y;
		cin >> x >> y;
		if (Num[y] > 0)
		{
			closed++;
			Num[y]--;
			if (Checked[y][x] > 0)
			{
				beautiful++;
				Checked[y][x]--;
			}
			else
				Rem[y]++;
		}
		else if (Checked[y][x] > 0 && Rem[y] > 0)
		{
			beautiful++;
			Checked[y][x]--;
			Rem[y]--;
		}
	}
	cout << closed << " " << beautiful << endl;
}


#include <iostream>
#include <algorithm>

using namespace std;

struct pt{
	int a, b;
	bool operator < (pt a2)
	{
		return b < a2.b || (b == a2.b && a < a2.a);
	}
};
int main()
{
	pt marker[10000], cap[10000];
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; i++)
		cin >> marker[i].a >> marker[i].b;
	sort(marker, marker + n);
	for (int i = 0; i < m; i++)
		cin >> cap[i].a >> cap[i].b;
	sort(cap, cap + m);
	int i = 0, j = 0, closed = 0, beautiful = 0;
	bool dontAdd = false;
	while(i < n && j < m)
	{
		if (marker[i].b < cap[j].b)
		{
			i++;
			continue;
		}
		if (cap[j].b < marker[i].b)
		{
			j++;
			continue;
		}
		if (!dontAdd)
			closed++;
		dontAdd = false;
		if (cap[j].a == marker[i].a)
			beautiful++;
		else if (cap[j + 1].b == cap[j].b)
		{
			if (cap[j].a < marker[i].a)
			{
				i--;
				dontAdd = true;
			}
			else
				j--;
		}
		i++, j++;
	}
	cout << closed << " " << beautiful << endl;

}


#include <iostream>

using namespace std;

int Checked[1010][1010];
int Num[1010];

int main()
{
	int n, m, closed = 0, beautiful = 0;
	cin >> n >> m;
	for (int i = 0; i < n; i++)
	{
		int a, b;
		cin >> a >> b;
		Num[b]++;
		Checked[b][a]++;
	}
	for (int i = 0; i < m; i++)
	{
		int x, y;
		cin >> x >> y;
		if (Num[y] > 0)
		{
			closed++;
			Num[y]--;
			if (Checked[y][x] > 0)
			{
				beautiful++;
				Checked[y][x]--;
			}
		}
	}
	cout << closed << " " << beautiful << endl;
}


#include <iostream>
#include <iomanip>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
struct O_o {
	ll x,y;
	bool operator< (const O_o &Typical_name)const {
		if (y != Typical_name.y) {
			return (y < Typical_name.y);
		} else {
			return (x < Typical_name.x);
		}
	}
};
struct T_T {
	string a,b;
	ll t;
};
ll n,m,i,j,h,g,o,p,l,a,b;
int f[1000][1000],k[1000][1000]
int main(){
	//freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
	//freopen("b.in", "r", stdin); freopen("b.out", "w", stdout);
	cin >> n >> m;
	for(i = 0; i < n; i++) {
		cin >> a >> b;
		f[a][b] ++;
	}
	for(i = 0; i < m; i++) {
		cin >> a >> b;
		k[a][b] ++;
	}

	for(j = 0; j <1000; j++) {
		h = g = 0;
		for(i = 0; i <1000; i++) {
			if(f[i][j] > 0 || k[i][j] > 0) {
				l = min(f[i][j],k[i][j]);
				o+=l;
				p+=l;
				h += f[i][j] - l;
				g += k[i][j] - l;
			}

		}
		o += min(h,g);
	}
	cout << o << ' ' << p;
	return 0;
}


#define _USE_MATH_DEFINES
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <string>
#include <assert.h>
#include <queue>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <random>
#include <cmath>

#define ll long long
#define ld long double
#define mp make_pair
#define pb push_back
#define int long long

using namespace std;

const int INF = 2e9;

vector<vector<pair<int, int>>> g;
vector<int> dp, s;
vector<bool> used;

void solve() {
	int n, m, s;
	cin >> n >> m >> s;
	s--;
	g.resize(n);
	vector<pair<int, pair<int, int>>> edges(m);
	for (int i = 0; i < m; i++) {
		int from, to, w;
		cin >> from >> to >> w;
		from--; to--;
		edges[i] = mp(w, mp(from, to));
		g[from].pb(mp(to, w));
		g[to].pb(mp(from, w));
	}
	int l;
	cin >> l;

	vector<int> dis(n, INF);
	set <pair<int, int>>st;
	dis[s] = 0;
	st.insert(mp(0, s));

	while (!st.empty()) {
		auto x = *st.begin();
		st.erase(x);
		int v = x.second;
		if (dis[v] < x.first) continue;

		for (auto & p : g[v]) {
			int u = p.first;
			int w = p.second;
			if (dis[u] > dis[v] + w) {
				dis[u] = dis[v] + w;
				st.insert(mp(dis[u], u));
			}
		}
	}

	int ans = 0;
	for (int i = 0; i < m; i++) {
		int w = edges[i].first;
		int from = edges[i].second.first;
		int to = edges[i].second.second;
		if (dis[from] < l && dis[from] + w > l) ans++;
		if ((dis[to] < l && dis[to] + w > l) && (w % 2 || l - dis[to] != l - dis[from] || l - dis[to] != w / 2) && l <= w / 2 + dis[to]) ans++;
	}
	for (int i = 0; i < n; i++) {
		if (dis[i] == l) ans++;
	}
	cout << ans;
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout.precision(12);
	/*
	freopen("distance4.in", "r", stdin);
	freopen("distance4.out", "w", stdout);
	*/
	solve();
}


#define _USE_MATH_DEFINES
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <string>
#include <assert.h>
#include <queue>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <random>
#include <cmath>

#define ll long long
#define ld long double
#define mp make_pair
#define pb push_back
#define int long long

using namespace std;

const int INF = 2e9;

void solve() {
	int n, m, s;
	cin >> n >> m >> s;
	s--;
	vector<vector<pair<int, int>>> g(n);
	vector<pair<int, pair<int, int>>> edges(m);
	for (int i = 0; i < m; i++) {
		int from, to, w;
		cin >> from >> to >> w;
		from--; to--;
		edges[i] = mp(w, mp(from, to));
		g[from].pb(mp(to, w));
		g[to].pb(mp(from, w));
	}
	int l;
	cin >> l;

	vector<int> dis(n, INF);
	set <pair<int, int>>st;
	dis[s] = 0;
	st.insert(mp(0, s));

	while (!st.empty()) {
		auto x = *st.begin();
		st.erase(x);
		int v = x.second;
		if (dis[v] < x.first) continue;

		for (auto & p : g[v]) {
			int u = p.first;
			int w = p.second;
			if (dis[u] > dis[v] + w) {
				dis[u] = dis[v] + w;
				st.insert(mp(dis[u], u));
			}
		}
	}

	int ans = 0;
	for (int i = 0; i < m; i++) {
		int w = edges[i].first;
		int from = edges[i].second.first;
		int to = edges[i].second.second;
		int x = l - dis[from];
		int y = l - dis[to];
		if (x < w && x >= 0) ans++;
		if (y < w && y >= 0 && dis[to] + y < dis[from] + (w - x)) ans++;
	}

	cout << ans;
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout.precision(12);
	/*
	freopen("distance4.in", "r", stdin);
	freopen("distance4.out", "w", stdout);
	*/
	solve();
}


#define _USE_MATH_DEFINES
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <string>
#include <assert.h>
#include <queue>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <random>
#include <cmath>

#define ll long long
#define ld long double
#define mp make_pair
#define pb push_back
#define int long long

using namespace std;

const int INF = 2e9;

void solve() {
	int n, m, s;
	cin >> n >> m >> s;
	s--;
	vector<vector<pair<int, int>>> g(n);
	vector<pair<int, pair<int, int>>> edges(m);
	for (int i = 0; i < m; i++) {
		int from, to, w;
		cin >> from >> to >> w;
		from--; to--;
		edges[i] = mp(w, mp(from, to));
		g[from].pb(mp(to, w));
		g[to].pb(mp(from, w));
	}
	int l;
	cin >> l;

	vector<int> dis(n, INF);
	set <pair<int, int>>st;
	dis[s] = 0;
	st.insert(mp(0, s));

	while (!st.empty()) {
		auto x = *st.begin();
		st.erase(x);
		int v = x.second;
		if (dis[v] < x.first) continue;

		for (auto & p : g[v]) {
			int u = p.first;
			int w = p.second;
			if (dis[u] > dis[v] + w) {
				dis[u] = dis[v] + w;
				st.insert(mp(dis[u], u));
			}
		}
	}

	int ans = 0;
	for (int i = 0; i < m; i++) {
		int w = edges[i].first;
		int from = edges[i].second.first;
		int to = edges[i].second.second;
		int x = l - dis[from];
		int y = l - dis[to];
		if (x < w && x >= 0 && dis[to] + x <= dis[from] + (w - x)) ans++;
		if (y < w && y >= 0 && dis[to] + y < dis[from] + (w - y)) ans++;
	}

	cout << ans;
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout.precision(12);
	/*
	freopen("distance4.in", "r", stdin);
	freopen("distance4.out", "w", stdout);
	*/
	solve();
}


#pragma GCC optimize("O2")
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<unordered_map>
#include<set>
#include<cmath>
#include<climits>
#include<random>
#include <iomanip>
#include <bitset>
#include <cassert>
using namespace std;

#define pb push_back
#define ff first
#define ss second
#define endl '\n'
#define fast ios::sync_with_stdio(false); cin.tie(NULL);

/////////////////////////////////////////////

void __print(int x) {cerr << x;}
void __print(long x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(unsigned x) {cerr << x;}
void __print(unsigned long x) {cerr << x;}
void __print(unsigned long long x) {cerr << x;}
void __print(float x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << '\'' << x << '\'';}
void __print(const char *x) {cerr << '\"' << x << '\"';}
void __print(const string &x) {cerr << '\"' << x << '\"';}
void __print(bool x) {cerr << (x ? "true" : "false");}

template<typename T, typename V>
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ','; __print(x.second); cerr << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), __print(i); cerr << "}";}
void _print() {cerr << "]\n";}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#ifndef ONLINE_JUDGE
#define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
#define debug(x...)
#endif

///////////////////////////////

#define int long long

const int N = 1e5 + 10;
vector<pair<int,int>> v[N];
bool vis[N];
int dist[N];
int n , m , s , l;
vector<vector<int>> edge;
void dfs(int s , int &cnt){

	vis[s] = true;
	for(auto it : v[s]){

		if(!vis[it.ff] && dist[it.ff] < l){

			dfs(it.ff , cnt);
		}

		if(dist[s] + it.ss > l)
			++cnt;
	}
}
int dijkstra(int s){

	fill(dist , dist + n + 1 , 1e17);
	bool vis[n + 1];
	memset(vis , false , sizeof vis);

	using T = pair<int,int> ;
	priority_queue<T , vector<T> , greater<T> > pq;
	pq.push({0 , s}); // <cost , source>
	dist[s] = 0;
	int cnt = 0;
	while(!pq.empty()){

		auto [cost , node] = pq.top();
		pq.pop();
		if(vis[node])
			continue;
		vis[node] = true;

		for(auto [child , paisa] : v[node]){

			if(dist[child] > paisa + cost){

				dist[child] = paisa + cost;
				pq.push({dist[child] , child});
			}
		}
	}
	int val = 0;
	for(int i = 1 ; i <= n ; ++i)
		cnt += (dist[i]==l);
	for(int i = 1 ; i <= n ; ++i)
		cout<<dist[i]<<" \n"[i==n];
	for(auto it : edge){

		int x = it[0];
		int y = it[1];
		int cost = it[2];
		if(dist[x] > dist[y])
			swap(x , y);
		if(dist[x] >= l)
			continue;
		set<int> col;
		if(dist[x] + cost > l){

			col.insert(l - dist[x]);
		}
		if(dist[y] < l && dist[y] + cost > l){

			col.insert(cost - l + dist[y]);
		}
		//debug(x , y, col);
		val += col.size();
	}
	//debug(val);
	return cnt + val;

}

void solve(){

	cin>>n>>m>>s;
	while(m--){

		int x, y , cost;
		cin>>x>>y>>cost;
		v[x].push_back({y , cost});
		v[y].push_back({x , cost});
		edge.push_back({x , y , cost});
	}
	cin>>l;
	cout<<dijkstra(s)<<endl;
}

signed main(){

	fast;
	int t = 1;
	//cin>>t;
	for(int i = 1 ; i <= t ; ++i)
		solve();
}


#pragma GCC optimize("O2")
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<unordered_map>
#include<set>
#include<cmath>
#include<climits>
#include<random>
#include <iomanip>
#include <bitset>
#include <cassert>
using namespace std;

#define pb push_back
#define ff first
#define ss second
#define endl '\n'
#define fast ios::sync_with_stdio(false); cin.tie(NULL);

/////////////////////////////////////////////

void __print(int x) {cerr << x;}
void __print(long x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(unsigned x) {cerr << x;}
void __print(unsigned long x) {cerr << x;}
void __print(unsigned long long x) {cerr << x;}
void __print(float x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << '\'' << x << '\'';}
void __print(const char *x) {cerr << '\"' << x << '\"';}
void __print(const string &x) {cerr << '\"' << x << '\"';}
void __print(bool x) {cerr << (x ? "true" : "false");}

template<typename T, typename V>
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ','; __print(x.second); cerr << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), __print(i); cerr << "}";}
void _print() {cerr << "]\n";}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#ifndef ONLINE_JUDGE
#define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
#define debug(x...)
#endif

///////////////////////////////

#define int long long

const int N = 1e5 + 10;
vector<pair<int,int>> v[N];
bool vis[N];
int dist[N];
int n , m , s , l;
vector<vector<int>> edge;
void dfs(int s , int &cnt){

	vis[s] = true;
	for(auto it : v[s]){

		if(!vis[it.ff] && dist[it.ff] < l){

			dfs(it.ff , cnt);
		}

		if(dist[s] + it.ss > l)
			++cnt;
	}
}
int dijkstra(int s){

	fill(dist , dist + n + 1 , 1e17);
	bool vis[n + 1];
	memset(vis , false , sizeof vis);

	using T = pair<int,int> ;
	priority_queue<T , vector<T> , greater<T> > pq;
	pq.push({0 , s}); // <cost , source>
	dist[s] = 0;
	int cnt = 0;
	while(!pq.empty()){

		auto [cost , node] = pq.top();
		pq.pop();
		if(vis[node])
			continue;
		vis[node] = true;

		for(auto [child , paisa] : v[node]){

			if(dist[child] > paisa + cost){

				dist[child] = paisa + cost;
				pq.push({dist[child] , child});
			}
		}
	}
	int val = 0;
	for(int i = 1 ; i <= n ; ++i)
		cnt += (dist[i]==l);
	// for(int i = 1 ; i <= n ; ++i)
	// 	cout<<dist[i]<<" \n"[i==n];
	for(auto it : edge){

		int x = it[0];
		int y = it[1];
		int cost = it[2];
		if(dist[x] > dist[y])
			swap(x , y);
		if(dist[x] >= l)
			continue;
		set<int> col;
		if(dist[x] + cost > l){

			col.insert(l - dist[x]);
		}
		if(dist[y] < l && dist[y] + cost > l){

			col.insert(cost - l + dist[y]);
		}
		//debug(x , y, col);
		val += col.size();
	}
	//debug(val);
	return cnt + val;

}

void solve(){

	cin>>n>>m>>s;
	while(m--){

		int x, y , cost;
		cin>>x>>y>>cost;
		v[x].push_back({y , cost});
		v[y].push_back({x , cost});
		edge.push_back({x , y , cost});
	}
	cin>>l;
	cout<<dijkstra(s)<<endl;
}

signed main(){

	fast;
	int t = 1;
	//cin>>t;
	for(int i = 1 ; i <= t ; ++i)
		solve();
}


#pragma GCC optimize("O2")
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<unordered_map>
#include<set>
#include<cmath>
#include<climits>
#include<random>
#include <iomanip>
#include <bitset>
#include <cassert>
using namespace std;

#define pb push_back
#define ff first
#define ss second
#define endl '\n'
#define fast ios::sync_with_stdio(false); cin.tie(NULL);

/////////////////////////////////////////////

void __print(int x) {cerr << x;}
void __print(long x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(unsigned x) {cerr << x;}
void __print(unsigned long x) {cerr << x;}
void __print(unsigned long long x) {cerr << x;}
void __print(float x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << '\'' << x << '\'';}
void __print(const char *x) {cerr << '\"' << x << '\"';}
void __print(const string &x) {cerr << '\"' << x << '\"';}
void __print(bool x) {cerr << (x ? "true" : "false");}

template<typename T, typename V>
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ','; __print(x.second); cerr << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), __print(i); cerr << "}";}
void _print() {cerr << "]\n";}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#ifndef ONLINE_JUDGE
#define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
#define debug(x...)
#endif

///////////////////////////////

#define int long long

const int N = 1e5 + 10;
vector<pair<int,int>> v[N];
bool vis[N];
int dist[N];
int n , m , s , l;
vector<vector<int>> edge;
void dfs(int s , int &cnt){

	vis[s] = true;
	for(auto it : v[s]){

		if(!vis[it.ff] && dist[it.ff] < l){

			dfs(it.ff , cnt);
		}

		if(dist[s] + it.ss > l)
			++cnt;
	}
}
int dijkstra(int s){

	fill(dist , dist + n + 1 , 1e17);
	bool vis[n + 1];
	memset(vis , false , sizeof vis);

	using T = pair<int,int> ;
	priority_queue<T , vector<T> , greater<T> > pq;
	pq.push({0 , s}); // <cost , source>
	dist[s] = 0;
	int cnt = 0;
	while(!pq.empty()){

		auto [cost , node] = pq.top();
		pq.pop();
		if(vis[node])
			continue;
		vis[node] = true;

		for(auto [child , paisa] : v[node]){

			if(dist[child] > paisa + cost){

				dist[child] = paisa + cost;
				pq.push({dist[child] , child});
			}
		}
	}
	int val = 0;
	for(int i = 1 ; i <= n ; ++i)
		cnt += (dist[i]==l);
	// for(int i = 1 ; i <= n ; ++i)
	// 	cout<<dist[i]<<" \n"[i==n];
	for(auto it : edge){

		int x = it[0];
		int y = it[1];
		int cost = it[2];
		set<int> col;
		if(dist[x] < l && dist[x] + cost > l){

			col.insert(l - dist[x]);
		}
		if(dist[y] < l && dist[y] + cost > l){

			col.insert(cost - l + dist[y]);
		}
		val += col.size();
	}
	//debug(val);
	return cnt + val;

}

void solve(){

	cin>>n>>m>>s;
	while(m--){

		int x, y , cost;
		cin>>x>>y>>cost;
		v[x].push_back({y , cost});
		v[y].push_back({x , cost});
		edge.push_back({x , y , cost});
	}
	cin>>l;
	cout<<dijkstra(s)<<endl;
}

signed main(){

	fast;
	int t = 1;
	//cin>>t;
	for(int i = 1 ; i <= t ; ++i)
		solve();
}


#pragma GCC optimize("O2")
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<unordered_map>
#include<set>
#include<cmath>
#include<climits>
#include<random>
#include <iomanip>
#include <bitset>
#include <cassert>
using namespace std;

#define pb push_back
#define ff first
#define ss second
#define endl '\n'
#define fast ios::sync_with_stdio(false); cin.tie(NULL);

/////////////////////////////////////////////

void __print(int x) {cerr << x;}
void __print(long x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(unsigned x) {cerr << x;}
void __print(unsigned long x) {cerr << x;}
void __print(unsigned long long x) {cerr << x;}
void __print(float x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << '\'' << x << '\'';}
void __print(const char *x) {cerr << '\"' << x << '\"';}
void __print(const string &x) {cerr << '\"' << x << '\"';}
void __print(bool x) {cerr << (x ? "true" : "false");}

template<typename T, typename V>
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ','; __print(x.second); cerr << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), __print(i); cerr << "}";}
void _print() {cerr << "]\n";}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#ifndef ONLINE_JUDGE
#define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
#define debug(x...)
#endif

///////////////////////////////

#define int long long

const int N = 1e5 + 10;
vector<pair<int,int>> v[N];
bool vis[N];
int dist[N];
int n , m , s , l;
vector<vector<int>> edge;
void dfs(int s , int &cnt){

	vis[s] = true;
	for(auto it : v[s]){

		if(!vis[it.ff] && dist[it.ff] < l){

			dfs(it.ff , cnt);
		}

		if(dist[s] + it.ss > l)
			++cnt;
	}
}
int dijkstra(int s){

	fill(dist , dist + n + 1 , 1e17);
	bool vis[n + 1];
	memset(vis , false , sizeof vis);

	using T = pair<int,int> ;
	priority_queue<T , vector<T> , greater<T> > pq;
	pq.push({0 , s}); // <cost , source>
	dist[s] = 0;
	int cnt = 0;
	while(!pq.empty()){

		auto [cost , node] = pq.top();
		pq.pop();
		if(vis[node])
			continue;
		vis[node] = true;

		for(auto [child , paisa] : v[node]){

			if(dist[child] > paisa + cost){

				dist[child] = paisa + cost;
				pq.push({dist[child] , child});
			}
		}
	}
	int val = 0;
	for(int i = 1 ; i <= n ; ++i)
		cnt += (dist[i]==l);
	// for(int i = 1 ; i <= n ; ++i)
	// 	cout<<dist[i]<<" \n"[i==n];
	for(auto it : edge){

		int x = it[0];
		int y = it[1];
		int cost = it[2];
		set<int> col;
		if(dist[x] < l && dist[x] + cost > l && cost - (l - dist[x]) + dist[y] >= l){

			col.insert(l - dist[x]);
		}
		if(dist[y] < l && dist[y] + cost > l && cost - (l - dist[y]) + dist[x] >= l){

			col.insert(cost - l + dist[y]);
		}
		val += col.size();
	}
	//debug(val);
	return cnt + val;

}

void solve(){

	cin>>n>>m>>s;
	while(m--){

		int x, y , cost;
		cin>>x>>y>>cost;
		v[x].push_back({y , cost});
		v[y].push_back({x , cost});
		edge.push_back({x , y , cost});
	}
	cin>>l;
	cout<<dijkstra(s)<<endl;
}

signed main(){

	fast;
	int t = 1;
	//cin>>t;
	for(int i = 1 ; i <= t ; ++i)
		solve();
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5+7, INF =1e9+7;
#define pii pair<int,int>
int n, m, s, l, dist[MAXN], ed[MAXN];
vector<pii> G[MAXN];
set<pii> aux;
priority_queue<pii, vector<pii>, greater<pii> > pq;
int main(){
    scanf("%d %d %d", &n, &m, &s);
    for(int i=1; i<=m; i++){
        int xi,yi,wi;
        scanf("%d %d %d", &xi, &yi, &wi);
        G[xi].push_back({yi, wi});
        G[yi].push_back({xi, wi});
    }
    for(int i=1; i<=n; i++){
        dist[i] = INF;
    }
    dist[s] = 0;
    pq.push({0,s});
    while(!pq.empty()){
        pii u = pq.top(); pq.pop();
        for(int i=0; i<(int)G[u.second].size(); i++){
            pii viz = G[u.second][i];
            if(dist[viz.first] > dist[u.second] + viz.second){
                dist[viz.first] = dist[u.second] + viz.second;
                ed[viz.first] = u.second;
                pq.push({dist[viz.first], viz.first});
            }
        }
    }
    scanf("%d", &l);
    int ans = 0;
    for(int i=1; i<=n; i++){
        //printf("--> %d\n", dist[i]);
        if(dist[i] == l){
            ans++;
        }
    }
    for(int i=1; i<=n; i++){
        for(int j=0; j<(int)G[i].size(); j++){
            if(aux.find({i,G[i][j].first})!=aux.end())continue;
            aux.insert({i,G[i][j].first});
            aux.insert({G[i][j].first, i});
            bool flag1 = false;
            bool flag2 = false;
            if(dist[i]<l && dist[i]+G[i][j].second>l && ed[i]!=G[i][j].first){
                //printf("%d %d\n", i, G[i][j].second);
                ans++;
                flag1 = true;
            }
            if(dist[G[i][j].first]<l && dist[G[i][j].first]+G[i][j].second>l && ed[G[i][j].first]!=i){
                //printf("%d %d\n", G[i][j].second, i);
                ans++;
                flag2=true;
            }
            if(flag1 && flag2 && dist[i]==dist[G[i][j].first] && 2*dist[i]+G[i][j].second==2*l){
                //printf("PONTO MEDIO %d %d\n", i, G[i][j].second);
                ans--;
            }
        }
    }
    printf("%d\n", ans);
}


//Missile Silos
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5+7, INF =1e9+7;
#define pii pair<int,int>
int n, m, s, l, dist[MAXN], ed[MAXN];
vector<pii> G[MAXN];
set<pii> aux;
priority_queue<pii, vector<pii>, greater<pii> > pq;
int main(){
    scanf("%d %d %d", &n, &m, &s);
    for(int i=1; i<=m; i++){
        int xi,yi,wi;
        scanf("%d %d %d", &xi, &yi, &wi);
        G[xi].push_back({yi, wi});
        G[yi].push_back({xi, wi});
    }
    for(int i=1; i<=n; i++){
        dist[i] = INF;
    }
    dist[s] = 0;
    pq.push({0,s});
    while(!pq.empty()){
        pii u = pq.top(); pq.pop();
        for(int i=0; i<(int)G[u.second].size(); i++){
            pii viz = G[u.second][i];
            if(dist[viz.first] > dist[u.second] + viz.second){
                dist[viz.first] = dist[u.second] + viz.second;
                ed[viz.first] = u.second;
                pq.push({dist[viz.first], viz.first});
            }
        }
    }
    scanf("%d", &l);
    int ans = 0;
    for(int i=1; i<=n; i++){
        //printf("--> %d\n", dist[i]);
        if(dist[i] == l){
            ans++;
        }
    }
    for(int i=1; i<=n; i++){
        for(int j=0; j<(int)G[i].size(); j++){
            if(aux.find({i,G[i][j].first})!=aux.end())continue;
            aux.insert({G[i][j].first, i});
            bool flag1 = false;
            bool flag2 = false;
            int u1 = i;
            int u2 = G[i][j].first;
            int w = G[i][j].second;
            //vamos ver quantos pontos estao sobre a aresta (i, G[i][j].first) com peso G[i][j].second
            if(dist[u1]<l && dist[u1]+w>l && w-(l-dist[u1])>l-dist[u2]){
                ans++;
            }
            if(dist[u2]<l && dist[u2]+w>l && w-(l-dist[u2])>l-dist[u1]){
                ans++;
            }
            if(dist[u1]<l && dist[u2]<l && dist[u1]+dist[u2]+w==2*l){
                ans++;
            }
        }
    }
    printf("%d\n", ans);
}


//Missile Silos
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5+7, INF =1e9+7;
#define pii pair<int,int>
int n, m, s, l, dist[MAXN], ed[MAXN];
vector<pii> G[MAXN];
set<pii> aux;
priority_queue<pii, vector<pii>, greater<pii> > pq;
int main(){
    scanf("%d %d %d", &n, &m, &s);
    for(int i=1; i<=m; i++){
        int xi,yi,wi;
        scanf("%d %d %d", &xi, &yi, &wi);
        G[xi].push_back({yi, wi});
        G[yi].push_back({xi, wi});
    }
    for(int i=1; i<=n; i++){
        dist[i] = INF;
    }
    dist[s] = 0;
    pq.push({0,s});
    while(!pq.empty()){
        pii u = pq.top(); pq.pop();
        for(int i=0; i<(int)G[u.second].size(); i++){
            pii viz = G[u.second][i];
            if(dist[viz.first] > dist[u.second] + viz.second){
                dist[viz.first] = dist[u.second] + viz.second;
                ed[viz.first] = u.second;
                pq.push({dist[viz.first], viz.first});
            }
        }
    }
    scanf("%d", &l);
    int ans = 0;
    for(int i=1; i<=n; i++){
        //printf("--> %d\n", dist[i]);
        if(dist[i] == l){
            ans++;
        }
    }
    for(int i=1; i<=n; i++){
        for(int j=0; j<(int)G[i].size(); j++){
            if(aux.find({i,G[i][j].first})!=aux.end())continue;
            aux.insert({G[i][j].first, i});
            bool flag1 = false;
            bool flag2 = false;
            int u1 = i;
            int u2 = G[i][j].first;
            int w = G[i][j].second;
            //vamos ver quantos pontos estao sobre a aresta (i, G[i][j].first) com peso G[i][j].second
            if(dist[u1]<l && dist[u1]+w>l && w-(l-dist[u1])>l-dist[u2]){
                ans++;
            }
            if(dist[u2]<l && dist[u2]+w>l && w-(l-dist[u2])>l-dist[u2]){
                ans++;
            }
            if(dist[u1]<l && dist[u2]<l && dist[u1]+dist[u2]+w==2*l){
                ans++;
            }
        }
    }
    printf("%d\n", ans);
}


#include <bits/stdc++.h>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;

constexpr int N = 1e5+5;

int n, m, s, l, a, b, w, p[N], d[N], ans = 0;
vector<pii> g[N];
map<pii, int> num;
set<int> st[N];

void bfs()
{
  priority_queue<pii> q;
  q.emplace(0, s);
  fill(d, d+N, 1e9);
  d[s] = 0;
  while (q.size())
  {
    auto [dist, v] = q.top();
    q.pop();
    for (auto [a, b]: g[v])
      if (d[v]+b < d[a])
      {
        d[a] = d[v] + b;
        p[a] = v;
        q.emplace(-d[a], a);
      }
  }
  for (int i = 1, cur, ch; i <= n; i++)
  {
    if (d[i] < l)
    {
      for (auto [a, b] : g[i])
        if (d[i]+b>l&&
        st[num[{min(i, a), max(i, a)}]].find((i==min(a, i))?l-d[i]:b-l+d[i])
        ==st[num[{min(i, a), max(i, a)}]].end())
          ans++, st[num[{min(i, a), max(i, a)}]].insert((i==min(a, i))?l-d[i]:b-l+d[i]);
    }
    else if (d[i]==l)
      ans++;
  }
}

void Solve()
{
  cin >> n >> m >> s;
  while(m--)
  {
    cin >> a >> b >> w;
    g[a].emplace_back(b, w);
    g[b].emplace_back(a, w);
    num[{min(a, b), max(a, b)}] = num.size();
  }
  cin >> l;
  bfs();
  cout << ans;
}

int main()
{
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  Solve();
  return 0;
}


#include <bits/stdc++.h>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;

constexpr int N = 1e2+5;

int n, m, s, l, a, b, w, p[N], d[N], ans = 0;
vector<pii> g[N];
map<pii, int> num;
int weight[N];
set<int> st[2][N];

void bfs()
{
  priority_queue<pii> q;
  q.emplace(0, s);
  fill(d, d+N, 1e9);
  d[s] = 0;
  while (q.size())
  {
    auto [dist, v] = q.top();
    q.pop();
    for (auto [a, b]: g[v])
      if (d[v]+b < d[a])
      {
        d[a] = d[v] + b;
        p[a] = v;
        q.emplace(-d[a], a);
      }
  }
  for (int i = 1, cur, ch; i <= n; i++)
  {
    if (d[i] < l)
    {
      for (auto [a, b] : g[i])
        if (d[i]+b>l)
          st[i<a][num[{min(i, a), max(i, a)}]].insert((i<a)?l-d[i]:b-l+d[i]);
    }
    else if (d[i]==l)
      ans++;
  }
  for (auto [a, b]: num)
  {
    if (st[0][b].size()&&st[1][b].size())
    {
      if (*(--st[0][b].end())>*st[1][b].begin())
        ans+=2;
      else if (*(--st[0][b].end())==*st[1][b].begin())
        ans++;
    }
    else
    {
      if (st[0][b].size()&&*(--st[0][b].end())+d[a.first]>=l)
        ans++;
      if (st[1][b].size()&&weight[b]-*st[1][b].begin()+d[a.second]>=l)
        ans++;
    }
  }
}

void Solve()
{
  cin >> n >> m >> s;
  while(m--)
  {
    cin >> a >> b >> w;
    g[a].emplace_back(b, w);
    g[b].emplace_back(a, w);
    weight[num.size()] = w;
    num[{min(a, b), max(a, b)}] = num.size();
  }
  cin >> l;
  bfs();
  cout << ans;
}

int main()
{
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  Solve();
  return 0;
}


#include <bits/stdc++.h>

#define endl "\n"
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;

constexpr int N = 1e5+5;

int n, m, s, l, a, b, w, p[N], d[N], ans = 0;
vector<pii> g[N];
map<pii, int> num;
int weight[N];
set<int> st[2][N];

void bfs()
{
  priority_queue<pii> q;
  q.emplace(0, s);
  fill(d, d+N, 1e9);
  d[s] = 0;
  while (q.size())
  {
    auto [dist, v] = q.top();
    q.pop();
    for (auto [a, b]: g[v])
      if (d[v]+b < d[a])
      {
        d[a] = d[v] + b;
        p[a] = v;
        q.emplace(-d[a], a);
      }
  }
  for (int i = 1, cur, ch; i <= n; i++)
  {
    if (d[i] < l)
    {
      for (auto [a, b] : g[i])
        if (d[i]+b>l)
          st[i<a][num[{min(i, a), max(i, a)}]].insert((i<a)?l-d[i]:b-l+d[i]);
    }
    else if (d[i]==l)
      ans++;
  }
  for (auto [a, b]: num)
  {
    if (st[0][b].size()&&st[1][b].size())
    {
      if (*(--st[0][b].end())>*st[1][b].begin())
        ans+=2;
      else if (*(--st[0][b].end())==*st[1][b].begin())
        ans++;
    }
    else
    {
      if (st[0][b].size()&&*(--st[0][b].end())+d[a.first]>=l)
        ans++;
      if (st[1][b].size()&&weight[b]-*st[1][b].begin()+d[a.second]>=l)
        ans++;
    }
  }
}

void Solve()
{
  cin >> n >> m >> s;
  while(m--)
  {
    cin >> a >> b >> w;
    g[a].emplace_back(b, w);
    g[b].emplace_back(a, w);
    weight[num.size()] = w;
    num[{min(a, b), max(a, b)}] = num.size();
  }
  cin >> l;
  bfs();
  cout << ans;
}

int main()
{
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  Solve();
  return 0;
}


#include<bits/stdc++.h>
using namespace std;

const int MAX=1e5+7;
typedef long long ll;
int n,m,src;
vector<pair<int,ll> > adj[MAX];
set<pair<ll,int> > s;
vector<pair<int,pair<int,int> > > e;
ll dist[MAX];
int p[MAX];
ll l;
void dijkstra(int src);

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

	cin>>n>>m>>src;
	for(int i=1;i<=m;++i){
		int u,v,w;
		cin>>u>>v>>w;
		adj[u].push_back(make_pair(v,w));
		adj[v].push_back(make_pair(u,w));
		e.push_back(make_pair(w,make_pair(u,v)));
	}
	cin>>l;
	ll res=0;
	dijkstra(src);
	for(int i=1;i<=n;++i){
		if(dist[i]==l){
			++res;
		}
	}

	for(int i=0;i<m;++i){
		ll w=e[i].first;
		int u=e[i].second.first;
		int v=e[i].second.second;
		if((dist[u]+w>l&&l>dist[u])||(dist[v]+w>l&&l>dist[v])){
			// "two points check"
			if((dist[u]+w>l&&l>dist[u])&&(dist[v]+w>l&&l>dist[v])){
				if(dist[u]+w-l+dist[v]==l){
					++res;
				}else{
				 if(l<dist[u]+w-l+dist[v]){
					++res;
				 }

				 if(l<dist[v]+w-l+dist[u]){
					++res;
				 }
			    }
			}else{
				if((dist[u]+w>l&&l>dist[u])&&l<dist[u]+w-l+dist[v]){
					++res;
				}

				if((dist[v]+w>l&&l>dist[v])&&l<dist[v]+w-l+dist[u]){
					++res;
				}
			}
		}
	}
	cout<<res<<"\n";
	return 0;
}

void dijkstra(int src){
	memset(dist,63,sizeof(dist));
	fill(p,p+n+1,-1);
	dist[src]=0;
	s.insert(make_pair(0,src));
	while(!s.empty()){
		pair<ll,int>a=*s.begin();
		s.erase(a);
		int cntNode=a.second;
		int size=adj[cntNode].size();
		for(int i=0;i<size;++i){
			pair<int,ll>x=adj[cntNode][i];
			int neigh=x.first;
			ll weight=x.second;
			if(weight+dist[cntNode]<dist[neigh]){
				s.erase(make_pair(dist[neigh],neigh));
				dist[neigh]=dist[cntNode]+weight;
				s.insert(make_pair(dist[neigh],neigh));
				p[neigh]=cntNode;
			}
		}
	}
}


#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int MAX=1e5+7;
vector<pair<ll,int> > adj[MAX];
set<pair<ll,int> > s;
ll dist[MAX];
int p[MAX];
void dijkstra(int src);
int n,m;
int src;
ll l;
vector<pair<ll,pair<int,int> > > e;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin>>n>>m>>src;
	for(int i=1;i<=m;++i){
		int u,v,w;
		cin>>u>>v>>w;
		adj[u].push_back(make_pair(v,w));
		adj[v].push_back(make_pair(u,w));
		e.push_back(make_pair(w,make_pair(u,v)));
	}
	ll res=0;
	cin>>l;
	dijkstra(src);
	for(int i=1;i<=n;++i){
		if(dist[i]==l){
			++res;
		}
	}

	for(int i=0;i<m;++i){
		int u=e[i].second.first;
		int v=e[i].second.second;
		ll w=e[i].first;
		if((dist[u]+w>l&&l>dist[u])&&(dist[v]+w>l&&l>dist[v])){
			if(dist[u]+w-l+dist[v]==l){
				++res;
			}else{
				if(l<dist[u]+w-l+dist[v]){
					++res;
				}

				if(l<dist[v]+w-l+dist[u]){
					++res;
				}
			}
		}else{
			if((dist[u]+w>l&&l>dist[u]&&l<dist[u]+w-l+dist[v])){
				++res;
			}

			if((dist[v]+w>l&&l>dist[v]&&l<dist[v]+w-l+dist[u])){
				++res;
			}
		}
	}
	cout<<res<<"\n";
	return 0;
}

void dijkstra(int src){
	memset(dist,63,sizeof(dist));
	fill(p,p+n+1,-1);
	dist[src]=0;
	s.insert(make_pair(0,src));
	while(!s.empty()){
		pair<ll,int>a=*s.begin();
		s.erase(a);
		int cntNode=a.second;
		int size=adj[cntNode].size();
		for(int i=0;i<size;++i){
			pair<int,ll>x=adj[cntNode][i];
			int neigh=x.first;
			ll weight=x.second;
			if(weight+dist[cntNode]<dist[neigh]){
				s.erase(make_pair(dist[neigh],neigh));
				dist[neigh]=weight+dist[cntNode];
				s.insert(make_pair(dist[neigh],neigh));
				p[neigh]=cntNode;
			}
		}
	}
}


#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int MAX=1e5+7;

vector<pair<int,ll> > adj[MAX];
set<pair<ll,int> > s;
vector<pair<ll,pair<int,int> > > e;
ll dist[MAX];
void dijkstra(int src);
int n,m,src;
ll l;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin>>n>>m>>src;
	for(int i=1;i<=m;++i){
		int u,v,w;
		cin>>u>>v>>w;
		adj[u].push_back(make_pair(v,w));
		adj[v].push_back(make_pair(u,w));
		e.push_back(make_pair(w,make_pair(u,v)));
	}
	cin>>l;
	dijkstra(src);
	int res=0;
	for(int i=1;i<=n;++i){
		if(dist[i]==l){
			++res;
		}
	}

	for(int i=0;i<m;++i){
		int u=e[i].second.first;
		int v=e[i].second.second;
		ll w=e[i].first;
		if((l>dist[u]&&l<dist[u]+w)||(l>dist[v]&&l<dist[v]+w)){
			if((l>dist[u]&&l<dist[u]+w)&&(l>dist[v]&&l<dist[v]+w)){
				if(dist[u]+w-l+dist[v]==l){
					++res;
				}else{
					if(dist[u]+w-l+dist[v]>l){
						++res;
					}

					if(dist[v]+w-l+dist[u]>l){
						++res;
					}
				}
			}else{
				if(l>dist[u]&&l<dist[u]+w&&dist[u]+w-l+dist[v]>l){
					++res;
				}else if(l>dist[v]&&l<dist[v]+w&&dist[v]+w-l+dist[u]>l){
					++res;
				}
			}
		}
	}
	cout<<res<<"\n";
	return 0;
}

void dijkstra(int src){
	memset(dist,63,sizeof(dist));
	dist[src]=0;
	s.insert(make_pair(0,src));
	while(!s.empty()){
		pair<ll,int> a=*s.begin();
		s.erase(a);
		int cntNode=a.second;
		int size=adj[cntNode].size();
		for(int i=0;i<size;++i){
			pair<int,ll> x=adj[cntNode][i];
			int neigh=x.first;
			ll weight=x.second;
			if(weight+dist[cntNode]<dist[neigh]){
				s.erase(make_pair(dist[neigh],neigh));
				dist[neigh]=dist[cntNode]+weight;
				s.insert(make_pair(dist[neigh],neigh));
			}
		}
	}
}


#include <bits/stdc++.h>
#define NMAX 100005
using namespace std;

int n, m, s, l, r;
set< pair<int, int> > v[NMAX];
int d[NMAX];

void dijkstra(int nod)
{
    set<pair<int, int>> h;
    memset(d, -1, NMAX);
    d[nod] = 0;
    bool vizitat[n+3];
    h.insert(make_pair(0, nod));

    while(!h.empty())
    {
        auto i = h.begin();
        h.erase(i);
        nod = (*i).second;
        vizitat[nod] = true;

        for(auto j: v[nod])
        {
            if(!vizitat[j.first] && (d[j.first]==-1 || d[j.first]>d[nod]+ j.second))
            {
                d[j.first] = d[nod]+ j.second;
                h.insert(make_pair(d[j.first], j.first));
            }
        }

    }
}

int main()
{
    cin>>n>>m>>s;
    int x, y, w;

    for(int i=0; i<m; i++)
    {
        cin>>x>>y>>w;
        v[x].insert(make_pair(y, w));
        v[y].insert(make_pair(x, w));
    }
    cin>>l;
    dijkstra(s);

    int c = 0;

    for(int i=1; i<=n; i++)
    {
        if(d[i] == l)
        {
            r++;
            continue;
        }
        if(d[i]>l)
            continue;

        for(auto j : v[i])
        {
            y = j.first;
            w = j.second;
            if(w-(l-d[i])+d[y]>l)
            {
                r++;
            }
            else if(d[i]<l && d[y]<l && d[i]+d[y]+w==2*l)
            {
               // cout<<i<< ' '<< y<<'\n';
                c++;
            }
        }
    }
    cout<<r+(c/2);
    return 0;
}


#include <bits/stdc++.h>
#define NMAX 100005
#define INF 0x3f3f3f3f
using namespace std;

int n, m, s, l, r;
set< pair<int, int> > v[NMAX];
int d[NMAX];

void dijkstra(int nod)
{
    set<pair<int, int>> h;
    memset(d, -1, sizeof(d));
    d[nod] = 0;
    h.insert(make_pair(0, nod));

    while(!h.empty())
    {
        auto i = h.begin();
        h.erase(i);
        nod = (*i).second;

        for(auto j: v[nod])
        {
            if(d[j.first]==-1 || d[j.first]>d[nod]+ j.second)
            {
                d[j.first] = d[nod]+ j.second;
                h.insert(make_pair(d[j.first], j.first));
            }
        }

    }
}

int main()
{
    cin>>n>>m>>s;
    int x, y, w;

    for(int i=0; i<m; i++)
    {
        cin>>x>>y>>w;
        v[x].insert(make_pair(y, w));
        v[y].insert(make_pair(x, w));
    }
    cin>>l;
    dijkstra(s);

    int c = 0;

    for(int i=1; i<=n; i++)
    {
        if(d[i] == l)
        {
            r++;
            continue;
        }
        if(d[i]>l)
            continue;

        for(auto j : v[i])
        {
            y = j.first;
            w = j.second;
            if(l-d[i]<w && w-(l-d[i])+d[y]>l)
            {
                r++;
            }
            else if(d[i]<l && d[y]<l && d[i]+d[y]+w==2*l)
            {
               // cout<<i<< ' '<< y<<'\n';
                c++;
            }
        }
    }
    cout<<r+(c/2);
    return 0;
}


#include <bits/stdc++.h>
#define NMAX 100005
using namespace std;

int n, m, s, l, r;
set< pair<int, int> > v[NMAX];
int d[NMAX];

void dijkstra(int nod)
{
    set<pair<int, int>> h;
    memset(d, -1, NMAX);
    d[nod] = 0;
    bool vizitat[n+3];
    h.insert(make_pair(0, nod));

    while(!h.empty())
    {
        auto i = h.begin();
        h.erase(i);
        nod = (*i).second;
        vizitat[nod] = true;

        for(auto j: v[nod])
        {
            if(!vizitat[j.first] && (d[j.first]==-1 || d[j.first]>d[nod]+ j.second))
            {
                d[j.first] = d[nod]+ j.second;
                h.insert(make_pair(d[j.first], j.first));
            }
        }

    }
}

int main()
{
    cin>>n>>m>>s;
    int x, y, w;

    for(int i=0; i<m; i++)
    {
        cin>>x>>y>>w;
        v[x].insert(make_pair(y, w));
        v[y].insert(make_pair(x, w));
    }
    cin>>l;
    dijkstra(s);

    int c = 0;

    for(int i=1; i<=n; i++)
    {
        if(d[i] == l)
        {
            r++;
            continue;
        }
        if(d[i]>l)
            continue;

        for(auto j : v[i])
        {
            y = j.first;
            w = j.second;
            if(l-d[i]<w && w-(l-d[i])+d[y]>l)
            {
                r++;
            }
            else if(d[i]<l && d[y]<l && d[i]+d[y]+w==2*l)
            {
               // cout<<i<< ' '<< y<<'\n';
                c++;
            }
        }
    }
    cout<<r+(c/2);
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define pb push_back

struct f
{
    int x,y;
    f(int _x, int _y)
    {
        x = _x;
        y = _y;
    }
};

vector <f> v[100010];
int d[100010];
int n, m, k, len;

void input()
{
    cin >> n >> m >> k;
    k--;
    for(int i = 0; i < m; i++)
    {
        int x, y, z;
        cin >> x >> y >> z;
        x--; y--;
        v[x].pb(f(y,z));
        v[y].pb(f(x,z));
    }
    cin >> len;
}

void solve()
{
    priority_queue <int> q;
    q.push(k);
    for(int i = 0; i < n; i++)
        d[i] = 1e9;
    d[k] = 0;
    while(!q.empty())
    {
        int cur = q.top();
        q.pop();
        for(int i = 0; i < v[cur].size(); i++)
        {
            int to = v[cur][i].x;
            int l = v[cur][i].y;
            if(d[to] < d[cur] + l)
                continue;
            d[to] = d[cur] + l;
            q.push(to);
        }
    }
    int ans = 0;
    for(int i = 0; i < n; i++)
        if(d[i] == len)
            ans++;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < v[i].size(); j++)
        {
            int fl = 1;
            int to = v[i][j].y + d[i];
            if(to < d[i] && to < len && len < d[i])
                ans++, fl = 0;
            else if(to > d[i] && to > len && len > d[i])
                ans++, fl = 0;
            if(!fl && v[i][j].x < i && v[i][j].y / 2 == len - d[i] && v[i][j].y % 2 == 0)
                ans--;
        }
    cout << ans;
}

int main() {
//  freopen("input.txt","r",stdin);
    //eopen("output.txt","w",stdout);
    input();
    solve();
}


#include <bits/stdc++.h>

using namespace std;

#define pb push_back

struct f
{
    int x,y;
    f(int _x, int _y)
    {
        x = _x;
        y = _y;
    }
};

vector <f> v[100010];
long long d[100010];
int n, m, k, len;

void input()
{
    cin >> n >> m >> k;
    k--;
    for(int i = 0; i < m; i++)
    {
        int x, y, z;
        cin >> x >> y >> z;
        x--; y--;
        v[x].pb(f(y,z));
        v[y].pb(f(x,z));
    }
    cin >> len;
}

void solve()
{
    priority_queue <pair <int,int> > q;
    q.push(pair <int,int> (0, k));
    for(int i = 0; i < n; i++)
        d[i] = 1e9;
    d[k] = 0;
    while(!q.empty())
    {
        int cur = q.top().second;
        int cur_d = q.top().first;
        q.pop();
        if(cur_d > d[cur])
            continue;
        for(int i = 0; i < v[cur].size(); i++)
        {
            int to = v[cur][i].x;
            int l = v[cur][i].y;
            if(d[to] <= d[cur] + l)
                continue;
            d[to] = d[cur] + l;
                q.push(pair <int,int> (-d[to], to));
        }
    }
    int ans = 0;

    for(int i = 0; i < n; i++)
        if(d[i] == len)
            ans++;
    for(int i = 0; i < n; i++)
        for(int r = 0; r < v[i].size(); r++)
        {
            int fl = 0;
            int j = v[i][r].x;
            int l = v[i][r].y;
            if(i > j)
                continue;
            if(d[i] < len && len - d[i] < l && l - len + d[i] + d[j] > len)
                ans++;
            if(d[j] < len && len - d[j] < l && l - len + d[i] + d[j] > len)
                ans++;
            if(d[j] < len & d[i] < len && d[i] + d[j] + l == len * 2)
                ans++;
        }
    cout << ans;
}

int main() {
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    input();
    solve();
}


#include <bits/stdc++.h>

using namespace std;

#define pb push_back

struct f
{
    int x,y;
    f(int _x, int _y)
    {
        x = _x;
        y = _y;
    }
};

vector <f> v[100010];
long long d[100010];
int n, m, k, len;

void input()
{
    cin >> n >> m >> k;
    k--;
    for(int i = 0; i < m; i++)
    {
        int x, y, z;
        cin >> x >> y >> z;
        x--; y--;
        v[x].pb(f(y,z));
        v[y].pb(f(x,z));
    }
    cin >> len;
}

void solve()
{
    priority_queue <int> q;
    q.push(k);
    for(int i = 0; i < n; i++)
        d[i] = 1e9;
    d[k] = 0;
    while(!q.empty())
    {
        int cur = q.top();
        q.pop();
        for(int i = 0; i < v[cur].size(); i++)
        {
            int to = v[cur][i].x;
            int l = v[cur][i].y;
            if(d[to] < d[cur] + l)
                continue;
            d[to] = d[cur] + l;
            q.push(to);
        }
    }
    int ans = 0;
    for(int i = 0; i < n; i++)
        if(d[i] == len)
            ans++;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < v[i].size(); j++)
        {
            int fl = 1;
            int to = v[i][j].x;
            int l = v[i][j].y;
            if(i > to)
                continue;

            if(d[to] < d[i] && d[to] < len && len < d[to] + l)
                ans++;
            else if(d[to] > d[i] && d[i] + l > len && len > d[i])
                ans++;
            else if(d[to] == d[i] && d[i] + l > len && len > d[to] && l / 2 != len - d[i])
                ans++;
            else if(d[to] == d[i] && d[i] + l > len && len > d[to] && l / 2 == len - d[i])
                ans+=2;
        }
    cout << ans;
}

int main() {
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    input();
    solve();
}


#include <bits/stdc++.h>

using namespace std;

#define pb push_back

struct f
{
    int x,y;
    f(int _x, int _y)
    {
        x = _x;
        y = _y;
    }
};

vector <f> v[100010];
int d[100010];
int n, m, k, len;

void input()
{
    cin >> n >> m >> k;
    k--;
    for(int i = 0; i < m; i++)
    {
        int x, y, z;
        cin >> x >> y >> z;
        x--; y--;
        v[x].pb(f(y,z));
        v[y].pb(f(x,z));
    }
    cin >> len;
}

void solve()
{
    priority_queue <int> q;
    q.push(k);
    for(int i = 0; i < n; i++)
        d[i] = 1e9;
    d[k] = 0;
    while(!q.empty())
    {
        int cur = q.top();
        q.pop();
        for(int i = 0; i < v[cur].size(); i++)
        {
            int to = v[cur][i].x;
            int l = v[cur][i].y;
            if(d[to] < d[cur] + l)
                continue;
            d[to] = d[cur] + l;
            q.push(to);
        }
    }
    int ans = 0;
    for(int i = 0; i < n; i++)
        if(d[i] == len)
            ans++;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < v[i].size(); j++)
        {
            int fl = 1;
            int to = v[i][j].x;
            int l = v[i][j].y;
            if(i > to)
                continue;

            if(d[to] < d[i] && d[to] < len && len < d[to] + l)
                ans++;
            else if(d[to] > d[i] && d[i] + l > len && len > d[i])
                ans++;
            else if(d[to] == d[i] && d[i] + l > len && len > d[to] && l / 2 != len - d[i])
                ans++;
            else if(d[to] == d[i] && d[i] + l > len && len > d[to] && l / 2 == len - d[i])
                ans+=2;
        }
    cout << ans;
}

int main() {
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    input();
    solve();
}


#include <bits/stdc++.h>

using namespace std;

#define pb push_back

struct f
{
    int x,y;
    f(int _x, int _y)
    {
        x = _x;
        y = _y;
    }
};

vector <f> v[100010];
long long d[100010];
int n, m, k, len;

void input()
{
    cin >> n >> m >> k;
    k--;
    for(int i = 0; i < m; i++)
    {
        int x, y, z;
        cin >> x >> y >> z;
        x--; y--;
        v[x].pb(f(y,z));
        v[y].pb(f(x,z));
    }
    cin >> len;
}

void solve()
{
    priority_queue <int> q;
    q.push(k);
    for(int i = 0; i < n; i++)
        d[i] = 1e9;
    d[k] = 0;
    while(!q.empty())
    {
        int cur = q.top();
        q.pop();
        for(int i = 0; i < v[cur].size(); i++)
        {
            int to = v[cur][i].x;
            int l = v[cur][i].y;
            if(d[to] <= d[cur] + l)
                continue;
            d[to] = d[cur] + l;
            q.push(to);
        }
    }
    int ans = 0;
    for(int i = 0; i < n; i++)
        if(d[i] == len)
            ans++;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < v[i].size(); j++)
        {
            int fl = 1;
            int to = v[i][j].x;
            int l = v[i][j].y;
            if(i > to)
                continue;

            if(d[to] < d[i] && d[to] < len && len < d[to] + l)
                ans++;
            else if(d[to] > d[i] && d[i] + l > len && len > d[i])
                ans++;
            else if(d[to] == d[i] && d[i] + l > len && len > d[to] && (l / 2 != len - d[i] || l % 2 == 1))
                ans++;
            else if(d[to] == d[i] && d[i] + l > len && len > d[to] && l / 2 == len - d[i] && l % 2 == 0)
                ans+=2;
        }
    cout << ans;
}

int main() {
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    input();
    solve();
}


#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 5, OO = 0x3f3f3f3f;

int n, m, s, l, cnt;
int dis[N];
vector<pair<int, int>> adj[N];

void dijkstra(int src)
{
	memset(dis, OO, sizeof dis);
	dis[src] = 0;
	priority_queue<pair<int, int>> q;
	q.push({0, src});
	while(!q.empty())
	{
		int u = q.top().second;
		int uc = -q.top().first;
		q.pop();
		if(dis[u] != uc)    continue;
		for(auto d : adj[u])
		{
			int c = d.first;
			int v = d.second;
			if(dis[v] > dis[u] + c)
			{
				dis[v] = dis[u] + c;
				q.push({-dis[v], v});
			}
		}
	}
}

int u, v, c;
int main()
{
	scanf("%d %d %d", &n, &m, &s);
	for(int i = 0 ; i < m; ++i)
	{
		scanf("%d %d %d", &u, &v, &c);
		adj[u].push_back({c, v});
		adj[v].push_back({c, u});
	}
	scanf("%d", &l);
	dijkstra(s);
	for(int i = 1 ; i <= n; ++i)
	{
		if(dis[i] == l)	++cnt;
		if(dis[i] >= l)	continue;
		for(auto r : adj[i])
		{
			int y = r.second, c = r.first;
			if(dis[i] + c <= l)	continue;
			if(dis[y] + c - (l - dis[i]) > l || dis[y] + c - (l - dis[i]) == l) ++cnt;
		}
	}
	cout << cnt << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 5, OO = 0x3f3f3f3f;

int n, m, s, l, cnt;
int dis[N];
vector<pair<int, int>> adj[N];

void dijkstra(int src)
{
	memset(dis, OO, sizeof dis);
	dis[src] = 0;
	priority_queue<pair<int, int>> q;
	q.push({0, src});
	while(!q.empty())
	{
		int u = q.top().second;
		int uc = -q.top().first;
		q.pop();
		if(dis[u] != uc)    continue;
		for(auto d : adj[u])
		{
			int c = d.first;
			int v = d.second;
			if(dis[v] > dis[u] + c)
			{
				dis[v] = dis[u] + c;
				q.push({-dis[v], v});
			}
		}
	}
}

int u, v, c;
int main()
{
	scanf("%d %d %d", &n, &m, &s);
	for(int i = 0 ; i < m; ++i)
	{
		scanf("%d %d %d", &u, &v, &c);
		adj[u].push_back({c, v});
		adj[v].push_back({c, u});
	}
	scanf("%d", &l);
	dijkstra(s);
	for(int i = 1 ; i <= n; ++i)
	{
		if(dis[i] == l)	++cnt;
		if(dis[i] >= l)	continue;
		for(auto r : adj[i])
		{
			int y = r.second, c = r.first;
			if(dis[i] + c <= l)	continue;
			if(dis[y] + c - (l - dis[i]) > l || dis[y] + c - (l - dis[i]) == l && i > y) ++cnt;
		}
	}
	cout << cnt << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 5, OO = 0x3f3f3f3f;

int n, m, s, l, cnt;
int dis[N];
vector<pair<int, int>> adj[N];

void dijkstra(int src)
{
	memset(dis, OO, sizeof dis);
	dis[src] = 0;
	priority_queue<pair<int, int>> q;
	q.push({0, src});
	while(!q.empty())
	{
		int u = q.top().second;
		int uc = -q.top().first;
		q.pop();
		if(dis[u] != uc)    continue;
		for(auto d : adj[u])
		{
			int c = d.first;
			int v = d.second;
			if(dis[v] > dis[u] + c)
			{
				dis[v] = dis[u] + c;
				q.push({-dis[v], v});
			}
		}
	}
}

int u, v, c;
int main()
{
	scanf("%d %d %d", &n, &m, &s);
	for(int i = 0 ; i < m; ++i)
	{
		scanf("%d %d %d", &u, &v, &c);
		adj[u].push_back({c, v});
		adj[v].push_back({c, u});
	}
	scanf("%d", &l);
	dijkstra(s);
	for(int i = 1 ; i <= n; ++i)
	{
		if(dis[i] == l)	++cnt;
		if(dis[i] >= l)	continue;
		for(auto r : adj[i])
		{
			int y = r.second, c = r.first;
			if(dis[i] + c <= l)	continue;
			if(dis[y] + c - (l - dis[i]) > l || dis[y] + c - (l - dis[i]) == l && i < y) ++cnt;
		}
	}
	printf("%d\n", cnt);
	return 0;
}


#include "bits/stdc++.h"
using namespace std;

typedef long long ll;
#define file freopen("in.txt", "r", stdin);

const int maxn = 1e5 + 5;
vector<ll> edges[maxn], cost[maxn];

int n, m, s;
ll ans = 0;
ll l;
vector<pair<pair<int, int>, int>> vec;
ll dis[maxn];

void dijkstra(int s){
    for(int i=0; i<maxn; i++)dis[i] = 1e15;
    dis[s] = 0;
    priority_queue<pair<int, int>> pq;
    pq.push({0, s});
    while(!pq.empty()){
        pair<int, int> s = pq.top();
        pq.pop();
        for(int i=0; i<(int)edges[s.second].size(); i++){
            int c = cost[s.second][i] + dis[s.second];
            if(dis[edges[s.second][i]] > c){
                dis[edges[s.second][i]] = c;
                pq.push({edges[s.second][i], dis[edges[s.second][i]]});
            }
        }
    }
}

int main(){
    //file
    scanf("%d %d %d", &n, &m, &s);
    for(int i=1; i<=m; i++){
        int x, y, z;
        scanf("%d %d %d", &x, &y, &z);
        edges[x].push_back(y);
        edges[y].push_back(x);
        cost[x].push_back(z);
        cost[y].push_back(z);
        vec.push_back(make_pair(make_pair(x, y), z));
    }
    scanf("%lld", &l);

    dijkstra(s);
    for(auto i : vec){
        if(i.second > l-dis[i.first.first] && dis[i.first.first] < l && i.second > l-dis[i.first.second] && dis[i.first.second] < l){
            if((l-dis[i.first.first])+(l-dis[i.first.second]) == i.second)ans++;
            else {
                ans += 2;
            }
        }else if(dis[i.first.first] < l && i.second > (l-dis[i.first.first])){
            ans++;
        }else if(dis[i.first.second] < l && i.second > (l-dis[i.first.second]))++ans;
    }
    for(int i=1; i<=n; i++)if(dis[i] == l)++ans;
    cout<<ans<<endl;
}


#include "bits/stdc++.h"
using namespace std;

typedef long long ll;
#define file freopen("in.txt", "r", stdin);

const int maxn = 1e5 + 5;
vector<ll> edges[maxn], cost[maxn], costs;
int n, m, s;
ll ans = 0;
ll l;

void dijkstra(int s){
    ll dis[maxn];
    for(int i=0; i<maxn; i++)dis[i] = 1e15;
    dis[s] = 0;
    priority_queue<pair<int, int>> pq;
    pq.push({0, s});
    while(!pq.empty()){
        pair<int, int> s = pq.top();
        pq.pop();
        for(int i=0; i<(int)edges[s.second].size(); i++){
            int c = cost[s.second][i] + dis[s.second];
            if(dis[edges[s.second][i]] > c){
                dis[edges[s.second][i]] = c;
                pq.push({edges[s.second][i], dis[edges[s.second][i]]});
            }
        }
    }
    for(int i=1; i<=n; i++){
        if(dis[i] == l)++ans;
    }
}

int main(){
   // file
    scanf("%d %d %d", &n, &m, &s);
    for(int i=1; i<=m; i++){
        int x, y, z;
        scanf("%d %d %d", &x, &y, &z);
        edges[x].push_back(y);
        edges[y].push_back(x);
        cost[x].push_back(z);
        cost[y].push_back(z);
        costs.push_back(z);
    }
    scanf("%lld", &l);
    dijkstra(s);
    for(auto i : costs){
        if(i == 2*l)ans += 2;
        else if(i >= l+1)++ans;
    }cout<<ans<<endl;
}


#include "bits/stdc++.h"
using namespace std;

typedef long long ll;
#define file freopen("in.txt", "r", stdin);

const int maxn = 1e5 + 5;
vector<ll> edges[maxn], cost[maxn];

int n, m, s;
double ans = 0;
ll l;
vector<pair<int, int>> vv[maxn];
ll dis[maxn];

void dijkstra(int s){
    for(int i=0; i<maxn; i++)dis[i] = 1e15;
    dis[s] = 0;
    priority_queue<pair<int, int>> pq;
    pq.push({0, s});
    while(!pq.empty()){
        pair<int, int> s = pq.top();
        pq.pop();
        for(int i=0; i<(int)edges[s.second].size(); i++){
            int c = cost[s.second][i] + dis[s.second];
            if(dis[edges[s.second][i]] > c){
                dis[edges[s.second][i]] = c;
                pq.push({edges[s.second][i], dis[edges[s.second][i]]});
            }
        }
    }
}

int main(){
   // file
    scanf("%d %d %d", &n, &m, &s);
    for(int i=1; i<=m; i++){
        int x, y, z;
        scanf("%d %d %d", &x, &y, &z);
        edges[x].push_back(y);
        edges[y].push_back(x);
        cost[x].push_back(z);
        cost[y].push_back(z);
        vv[x].push_back(make_pair(y, z));
        vv[y].push_back(make_pair(x, z));
    }
    scanf("%lld", &l);

    dijkstra(s);
    for(int i=1; i<=n; i++){
        for(auto j : vv[i]){
            if(dis[i] < l && l < dis[i] + j.second){
                if(l <= dis[j.first] + j.second - (l-dis[i]))ans++;
                if(l == dis[j.first] + j.second - (l-dis[i]))ans -= .5;
            }
        }
    }

    for(int i=1; i<=n; i++)if(dis[i] == l)++ans;
    cout<<ans<<endl;
}


#include "bits/stdc++.h"
using namespace std;

typedef long long ll;
#define file freopen("in.txt", "r", stdin);

const int maxn = 1e5 + 5;
vector<ll> edges[maxn], cost[maxn];

int n, m, s;
double ans = 0;
ll l;
vector<pair<int, int>> vv[maxn];
ll dis[maxn];

void dijkstra(int s){
    for(int i=0; i<maxn; i++)dis[i] = 1e15;
    dis[s] = 0;
    priority_queue<pair<int, int>> pq;
    pq.push({0, s});
    while(!pq.empty()){
        pair<int, int> s = pq.top();
        pq.pop();
        for(int i=0; i<(int)edges[s.second].size(); i++){
            int c = cost[s.second][i] + dis[s.second];
            if(dis[edges[s.second][i]] > c){
                dis[edges[s.second][i]] = c;
                pq.push({dis[edges[s.second][i]], edges[s.second][i]});
            }
        }
    }
}

int main(){
    //file
    scanf("%d %d %d", &n, &m, &s);
    for(int i=1; i<=m; i++){
        int x, y, z;
        scanf("%d %d %d", &x, &y, &z);
        edges[x].push_back(y);
        edges[y].push_back(x);
        cost[x].push_back(z);
        cost[y].push_back(z);
        vv[x].push_back(make_pair(y, z));
        vv[y].push_back(make_pair(x, z));
    }
    scanf("%lld", &l);

    dijkstra(s);
    for(int i=1; i<=n; i++){
        for(auto e : vv[i]){
            int j = e.first, k = e.second;
            if(dis[i] < l && l < dis[i] + k){
                int d1 = dis[j] + k - (l-dis[i]);
                if(l <= d1)ans++;
                if(l == d1)ans -= .5;
            }
        }
    }

    for(int i=1; i<=n; i++)if(dis[i] == l)++ans;
    cout<<ans<<endl;
}


#include "bits/stdc++.h"
using namespace std;

typedef long long ll;
#define file freopen("in.txt", "r", stdin);

const int maxn = 1e5 + 5;
vector<ll> edges[maxn], cost[maxn];

int n, m, s;
ll ans = 0;
ll l;
vector<pair<pair<int, int>, int>> vec;
ll dis[maxn];

void dijkstra(int s){
    for(int i=0; i<maxn; i++)dis[i] = 1e15;
    dis[s] = 0;
    priority_queue<pair<int, int>> pq;
    pq.push({0, s});
    while(!pq.empty()){
        pair<int, int> s = pq.top();
        pq.pop();
        for(int i=0; i<(int)edges[s.second].size(); i++){
            int c = cost[s.second][i] + dis[s.second];
            if(dis[edges[s.second][i]] > c){
                dis[edges[s.second][i]] = c;
                pq.push({edges[s.second][i], dis[edges[s.second][i]]});
            }
        }
    }
}

int main(){
   // file
    scanf("%d %d %d", &n, &m, &s);
    for(int i=1; i<=m; i++){
        int x, y, z;
        scanf("%d %d %d", &x, &y, &z);
        edges[x].push_back(y);
        edges[y].push_back(x);
        cost[x].push_back(z);
        cost[y].push_back(z);
        vec.push_back(make_pair(make_pair(x, y), z));
    }
    scanf("%lld", &l);

    dijkstra(s);
    for(auto i : vec){
        if(i.second > (l-dis[i.first.first]) && i.second > (l-dis[i.first.second]) && dis[i.first.first] < l && dis[i.first.second] < l){
            if((l-dis[i.first.first])+(l-dis[i.first.second]) == i.second)ans++;
            else {
                ans += 2;
            }
        }else if(dis[i.first.first] < l && i.second > (l-dis[i.first.first])){
            ans++;
        }else if(dis[i.first.second] < l && i.second > (l-dis[i.first.second]))++ans;
    }
    for(int i=1; i<=n; i++)if(dis[i] == l)++ans;
    cout<<ans<<endl;
}


#include "bits/stdc++.h"
using namespace std;

typedef long long ll;
#define file freopen("in.txt", "r", stdin);

const int maxn = 1e5 + 5;
vector<ll> edges[maxn], cost[maxn], costs;
int n, m, s;
ll ans = 0;
ll l;

void dijkstra(int s){
    ll dis[maxn];
    for(int i=0; i<maxn; i++)dis[i] = 1e15;
    dis[s] = 0;
    priority_queue<pair<int, int>> pq;
    pq.push({0, s});
    while(!pq.empty()){
        pair<int, int> s = pq.top();
        pq.pop();
        for(int i=0; i<(int)edges[s.second].size(); i++){
            int c = cost[s.second][i] + dis[s.second];
            if(dis[edges[s.second][i]] > c){
                dis[edges[s.second][i]] = c;
                pq.push({edges[s.second][i], dis[edges[s.second][i]]});
            }
        }
    }
    for(int i=1; i<=n; i++){
        if(dis[i] == l)++ans;
    }
}

int main(){
   // file
    scanf("%d %d %d", &n, &m, &s);
    for(int i=1; i<=m; i++){
        int x, y, z;
        scanf("%d %d %d", &x, &y, &z);
        edges[x].push_back(y);
        edges[y].push_back(x);
        cost[x].push_back(z);
        cost[y].push_back(z);
        costs.push_back(z);
    }
    scanf("%lld", &l);
    if(l == 0){
        cout<<"1"<<endl;
        return 0;
    }
    dijkstra(s);
    for(auto i : costs){
        if(i == 2*l)ans += 2;
        else if(i >= l+1)++ans;
    }cout<<ans<<endl;
}


#include "bits/stdc++.h"
using namespace std;

typedef long long ll;
#define file freopen("in.txt", "r", stdin);

const int maxn = 1e5 + 5;
vector<ll> edges[maxn], cost[maxn];

int n, m, s;
double ans = 0;
ll l;
vector<pair<int, int>> vv[maxn];
ll dis[maxn];

void dijkstra(int s){
    for(int i=0; i<maxn; i++)dis[i] = 1e15;
    dis[s] = 0;
    priority_queue<pair<int, int>> pq;
    pq.push({0, s});
    while(!pq.empty()){
        pair<int, int> s = pq.top();
        pq.pop();
        for(int i=0; i<(int)edges[s.second].size(); i++){
            int c = cost[s.second][i] + dis[s.second];
            if(dis[edges[s.second][i]] > c){
                dis[edges[s.second][i]] = c;
                pq.push({-dis[edges[s.second][i]], edges[s.second][i]});
            }
        }
    }
}

int main(){
    //file
    scanf("%d %d %d", &n, &m, &s);
    for(int i=1; i<=m; i++){
        int x, y, z;
        scanf("%d %d %d", &x, &y, &z);
        edges[x].push_back(y);
        edges[y].push_back(x);
        cost[x].push_back(z);
        cost[y].push_back(z);
        vv[x].push_back(make_pair(y, z));
        vv[y].push_back(make_pair(x, z));
    }
    scanf("%lld", &l);

    dijkstra(s);
    for(int i=1; i<=n; i++){
        for(auto e : vv[i]){
            int j = e.first, k = e.second;
            if(dis[i] < l && l < dis[i] + k){
                int d1 = dis[j] + k - (l-dis[i]);
                if(l <= d1)ans++;
                if(l == d1)ans -= .5;
            }
        }
    }

    for(int i=1; i<=n; i++)if(dis[i] == l)++ans;
    cout<<ans<<endl;
}


#include <bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define M 1000000007
#define M2 998244353
#define ll long long
#define pll pair<long,long>
#define REP(i,a,b) for(ll i=a;i<b;i++)
#define REPI(i,a,b) for(ll i=b-1;i>=a;i--)
#define ff first
#define ss second
#define pb push_back
#define db pop_back
#define mp make_pair
#define mt make_tuple
#define g(a,b) get<a>(b)
#define INF 1e18

#define o_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define o_setll tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>
//member functions :
//1. order_of_key(k) : number of elements strictly lesser than k
//2. find_by_order(k) : k-th element in the set

ll modI(ll a, ll m);
ll gcd(ll a, ll b);
ll powM(ll x, unsigned ll y, unsigned ll m);
void pairsort(int a[], int b[], int n);
void pairsortll(ll a[],ll b[],ll n);
ll logint(ll x,ll y);

ll gcd(ll x,ll y)
{
    if(x==0) return y;
    return gcd(y%x,x);
}

ll powM(ll x,ll y,ll m)
{
    if(y==0) return 1;
    ll p=powM(x,y/2,m)%m;
    p=(p*p)%m;
    return (y%2==0)?p:(x*p)%m;
}

ll modI(ll a, ll m)
{
   return powM(a, m-2, m);
}

void pairsort(int a[],int b[],int n)
{
    pair<int,int> v[n];
    REP(i,0,n)
    {
        v[i].ff=a[i];
        v[i].ss=b[i];
    }
    sort(v,v+n);
    REP(i,0,n)
    {
        a[i]=v[i].ff;
        b[i]=v[i].ss;
    }
}

void pairsortll(ll a[],ll b[],ll n)
{
    pair<ll,ll> v[n];
    REP(i,0,n)
    {
        v[i].ff=a[i];
        v[i].ss=b[i];
    }
    sort(v,v+n);
    REP(i,0,n)
    {
        a[i]=v[i].ff;
        b[i]=v[i].ss;
    }
}

ll logint(ll x,ll y)
{
    ll ans=0;
    ll a=1;
    for(ll i=0;i<=x;i++)
    {
        if(x<a)
        {
            return ans;
        }
        ans++;
        a*=y;
    }
    return -1;
}
ll dist[100001];
vector<pair<ll, ll> >v[100001];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    ll n, m, s;
    cin>>n>>m>>s;

    ll ar[m][3];
    REP(i, 0, m){
        ll x, y, w;
        cin>>x>>y>>w;
        ar[i][0] = x;
        ar[i][1] = y;
        ar[i][2] = w;
        v[x].pb({w, y});
        v[y].pb({w, x});
    }
    ll l;
    cin>>l;
    REP(i, 0, n+1){
        dist[i] = INF;
    }
    priority_queue< pair<ll, ll>, vector<pair<ll, ll> >, greater<pair<ll, ll> > >pq;
    dist[s] = 0;
    pq.push({0, s});
    while(!pq.empty()){
        ll a = pq.top().ff;
        ll b = pq.top().ss;
        pq.pop();
        if(a > dist[b]){continue;}
        for(auto x : v[b]){
            if(dist[b]+x.ff < dist[x.ss]){
                dist[x.ss] = dist[b]+x.ff;
                pq.push({dist[x.ss], x.ss});
            }
        }
    }
    //cout<<dist[3]<<endl;
    ll ans=0;
    REP(i, 1, n+1){
        if(dist[i] == l){ans++; //cout<<i<<" ";
        }
    }
    //cout<<endl;
    REP(i, 0, m){
        double mini = min((double)dist[ar[i][0]], (double)dist[ar[i][1]]);
        double maxi = max((double)dist[ar[i][0]], (double)dist[ar[i][1]]);
        double weight = (double)ar[i][2];
        double x = (maxi-mini+weight)/(2*weight);
        if((double)l > mini && maxi > (double)l){ans++;}
        else if(x > 0 && x < 1){
            if(mini+x*weight == (double)l){ans++;}
            else if(mini+x*weight > (double)l){ans+=2;
                if(maxi == (double)l){ans--;}
                if(mini == (double)l){ans--;}
            }
        }
    }
    cout<<ans;

}


#include <bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define M 1000000007
#define M2 998244353
#define ll long long
#define pll pair<long,long>
#define REP(i,a,b) for(ll i=a;i<b;i++)
#define REPI(i,a,b) for(ll i=b-1;i>=a;i--)
#define ff first
#define ss second
#define pb push_back
#define db pop_back
#define mp make_pair
#define mt make_tuple
#define g(a,b) get<a>(b)
#define INF 1e18

#define o_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define o_setll tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>
//member functions :
//1. order_of_key(k) : number of elements strictly lesser than k
//2. find_by_order(k) : k-th element in the set

ll modI(ll a, ll m);
ll gcd(ll a, ll b);
ll powM(ll x, unsigned ll y, unsigned ll m);
void pairsort(int a[], int b[], int n);
void pairsortll(ll a[],ll b[],ll n);
ll logint(ll x,ll y);

ll gcd(ll x,ll y)
{
    if(x==0) return y;
    return gcd(y%x,x);
}

ll powM(ll x,ll y,ll m)
{
    if(y==0) return 1;
    ll p=powM(x,y/2,m)%m;
    p=(p*p)%m;
    return (y%2==0)?p:(x*p)%m;
}

ll modI(ll a, ll m)
{
   return powM(a, m-2, m);
}

void pairsort(int a[],int b[],int n)
{
    pair<int,int> v[n];
    REP(i,0,n)
    {
        v[i].ff=a[i];
        v[i].ss=b[i];
    }
    sort(v,v+n);
    REP(i,0,n)
    {
        a[i]=v[i].ff;
        b[i]=v[i].ss;
    }
}

void pairsortll(ll a[],ll b[],ll n)
{
    pair<ll,ll> v[n];
    REP(i,0,n)
    {
        v[i].ff=a[i];
        v[i].ss=b[i];
    }
    sort(v,v+n);
    REP(i,0,n)
    {
        a[i]=v[i].ff;
        b[i]=v[i].ss;
    }
}

ll logint(ll x,ll y)
{
    ll ans=0;
    ll a=1;
    for(ll i=0;i<=x;i++)
    {
        if(x<a)
        {
            return ans;
        }
        ans++;
        a*=y;
    }
    return -1;
}
ll dist[100001];
vector<pair<ll, ll> >v[100001];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    ll n, m, s;
    cin>>n>>m>>s;

    ll ar[m][3];
    REP(i, 0, m){
        ll x, y, w;
        cin>>x>>y>>w;
        ar[i][0] = x;
        ar[i][1] = y;
        ar[i][2] = w;
        v[x].pb({w, y});
        v[y].pb({w, x});
    }
    ll l;
    cin>>l;
    REP(i, 0, n+1){
        dist[i] = INF;
    }
    priority_queue< pair<ll, ll>, vector<pair<ll, ll> >, greater<pair<ll, ll> > >pq;
    dist[s] = 0;
    pq.push({0, s});
    while(!pq.empty()){
        ll a = pq.top().ff;
        ll b = pq.top().ss;
        pq.pop();
        if(a > dist[b]){continue;}
        for(auto x : v[b]){
            if(dist[b]+x.ff < dist[x.ss]){
                dist[x.ss] = dist[b]+x.ff;
                pq.push({dist[x.ss], x.ss});
            }
        }
    }
    //cout<<dist[3]<<endl;
    ll ans=0;
    REP(i, 1, n+1){
        if(dist[i] == l){ans++;}
    }
    REP(i, 0, m){
        double mini = min((double)dist[ar[i][0]], (double)dist[ar[i][1]]);
        double maxi = max((double)dist[ar[i][0]], (double)dist[ar[i][1]]);
        double weight = (double)ar[i][2];
        double x = (maxi-mini+weight)/(2*weight);
        if(mini >= (double)l){continue;}
        if(x == 1 && maxi > (double)l){ans++;}
        else if(x > 0 && x < 1){
            if(mini+x*weight == (double)l){ans++;}
            else if(mini+x*weight > (double)l){ans+=2;}
        }
    }
    //cout<<endl;
    cout<<ans;

}


#include <bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define M 1000000007
#define M2 998244353
#define ll long long
#define pll pair<long,long>
#define REP(i,a,b) for(ll i=a;i<b;i++)
#define REPI(i,a,b) for(ll i=b-1;i>=a;i--)
#define ff first
#define ss second
#define pb push_back
#define db pop_back
#define mp make_pair
#define mt make_tuple
#define g(a,b) get<a>(b)
#define INF 1e18

#define o_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define o_setll tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>
//member functions :
//1. order_of_key(k) : number of elements strictly lesser than k
//2. find_by_order(k) : k-th element in the set

ll modI(ll a, ll m);
ll gcd(ll a, ll b);
ll powM(ll x, unsigned ll y, unsigned ll m);
void pairsort(int a[], int b[], int n);
void pairsortll(ll a[],ll b[],ll n);
ll logint(ll x,ll y);

ll gcd(ll x,ll y)
{
    if(x==0) return y;
    return gcd(y%x,x);
}

ll powM(ll x,ll y,ll m)
{
    if(y==0) return 1;
    ll p=powM(x,y/2,m)%m;
    p=(p*p)%m;
    return (y%2==0)?p:(x*p)%m;
}

ll modI(ll a, ll m)
{
   return powM(a, m-2, m);
}

void pairsort(int a[],int b[],int n)
{
    pair<int,int> v[n];
    REP(i,0,n)
    {
        v[i].ff=a[i];
        v[i].ss=b[i];
    }
    sort(v,v+n);
    REP(i,0,n)
    {
        a[i]=v[i].ff;
        b[i]=v[i].ss;
    }
}

void pairsortll(ll a[],ll b[],ll n)
{
    pair<ll,ll> v[n];
    REP(i,0,n)
    {
        v[i].ff=a[i];
        v[i].ss=b[i];
    }
    sort(v,v+n);
    REP(i,0,n)
    {
        a[i]=v[i].ff;
        b[i]=v[i].ss;
    }
}

ll logint(ll x,ll y)
{
    ll ans=0;
    ll a=1;
    for(ll i=0;i<=x;i++)
    {
        if(x<a)
        {
            return ans;
        }
        ans++;
        a*=y;
    }
    return -1;
}
ll dist[100001];
vector<pair<ll, ll> >v[100001];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    ll n, m, s;
    cin>>n>>m>>s;

    ll ar[m][3];
    REP(i, 0, m){
        ll x, y, w;
        cin>>x>>y>>w;
        ar[i][0] = x;
        ar[i][1] = y;
        ar[i][2] = w;
        v[x].pb({w, y});
        v[y].pb({w, x});
    }
    ll l;
    cin>>l;
    REP(i, 0, n+1){
        dist[i] = INF;
    }
    priority_queue< pair<ll, ll>, vector<pair<ll, ll> >, greater<pair<ll, ll> > >pq;
    dist[s] = 0;
    pq.push({0, s});
    while(!pq.empty()){
        ll a = pq.top().ff;
        ll b = pq.top().ss;
        pq.pop();
        if(a > dist[b]){continue;}
        for(auto x : v[b]){
            if(dist[b]+x.ff < dist[x.ss]){
                dist[x.ss] = dist[b]+x.ff;
                pq.push({dist[x.ss], x.ss});
            }
        }
    }
    //cout<<dist[3]<<endl;
    ll ans=0;
    REP(i, 1, n+1){
        if(dist[i] == l){ans++;}
    }
    REP(i, 0, m){
        double mini = min((double)dist[ar[i][0]], (double)dist[ar[i][1]]);
        double maxi = max((double)dist[ar[i][0]], (double)dist[ar[i][1]]);
        double weight = (double)ar[i][2];
        double x = (maxi-mini+weight)/(2*weight);
        if(mini+x*weight > (double)l){ans+=2;
        }
        else if(mini+x*weight == (double)l){ans++;
        }
        if(dist[ar[i][0]] == l){ans--;}
        if(dist[ar[i][1]] == l){ans--;}
    }
    //cout<<endl;
    cout<<ans;

}


#include <bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define M 1000000007
#define M2 998244353
#define ll long long
#define pll pair<long,long>
#define REP(i,a,b) for(ll i=a;i<b;i++)
#define REPI(i,a,b) for(ll i=b-1;i>=a;i--)
#define ff first
#define ss second
#define pb push_back
#define db pop_back
#define mp make_pair
#define mt make_tuple
#define g(a,b) get<a>(b)
#define INF 1e18

#define o_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define o_setll tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>
//member functions :
//1. order_of_key(k) : number of elements strictly lesser than k
//2. find_by_order(k) : k-th element in the set

ll modI(ll a, ll m);
ll gcd(ll a, ll b);
ll powM(ll x, unsigned ll y, unsigned ll m);
void pairsort(int a[], int b[], int n);
void pairsortll(ll a[],ll b[],ll n);
ll logint(ll x,ll y);

ll gcd(ll x,ll y)
{
    if(x==0) return y;
    return gcd(y%x,x);
}

ll powM(ll x,ll y,ll m)
{
    if(y==0) return 1;
    ll p=powM(x,y/2,m)%m;
    p=(p*p)%m;
    return (y%2==0)?p:(x*p)%m;
}

ll modI(ll a, ll m)
{
   return powM(a, m-2, m);
}

void pairsort(int a[],int b[],int n)
{
    pair<int,int> v[n];
    REP(i,0,n)
    {
        v[i].ff=a[i];
        v[i].ss=b[i];
    }
    sort(v,v+n);
    REP(i,0,n)
    {
        a[i]=v[i].ff;
        b[i]=v[i].ss;
    }
}

void pairsortll(ll a[],ll b[],ll n)
{
    pair<ll,ll> v[n];
    REP(i,0,n)
    {
        v[i].ff=a[i];
        v[i].ss=b[i];
    }
    sort(v,v+n);
    REP(i,0,n)
    {
        a[i]=v[i].ff;
        b[i]=v[i].ss;
    }
}

ll logint(ll x,ll y)
{
    ll ans=0;
    ll a=1;
    for(ll i=0;i<=x;i++)
    {
        if(x<a)
        {
            return ans;
        }
        ans++;
        a*=y;
    }
    return -1;
}
ll dist[100001];
vector<pair<ll, ll> >v[100001];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    ll n, m, s;
    cin>>n>>m>>s;

    ll ar[m][3];
    REP(i, 0, m){
        ll x, y, w;
        cin>>x>>y>>w;
        ar[i][0] = x;
        ar[i][1] = y;
        ar[i][2] = w;
        v[x].pb({w, y});
        v[y].pb({w, x});
    }
    ll l;
    cin>>l;
    REP(i, 0, n+1){
        dist[i] = INF;
    }
    priority_queue< pair<ll, ll>, vector<pair<ll, ll> >, greater<pair<ll, ll> > >pq;
    dist[s] = 0;
    pq.push({0, s});
    while(!pq.empty()){
        ll a = pq.top().ff;
        ll b = pq.top().ss;
        pq.pop();
        if(a > dist[b]){continue;}
        for(auto x : v[b]){
            if(dist[b]+x.ff < dist[x.ss]){
                dist[x.ss] = dist[b]+x.ff;
                pq.push({dist[x.ss], x.ss});
            }
        }
    }
    //cout<<dist[3]<<endl;
    ll ans=0;
    REP(i, 1, n+1){
        if(dist[i] == l){ans++; //cout<<i<<" ";
        }
    }
    //cout<<endl;
    REP(i, 0, m){
        double mini = min((double)dist[ar[i][0]], (double)dist[ar[i][1]]);
        double maxi = max((double)dist[ar[i][0]], (double)dist[ar[i][1]]);
        double weight = (double)ar[i][2];
        double x = (maxi-mini+weight)/(2*weight);
        if(mini >= (double)l){continue;}
        if(x == 1 && maxi > (double)l){ans++;}
        else if(x > 0 && x < 1){
            if(mini+x*weight == (double)l){ans++;}
            else if(mini+x*weight > (double)l){ans+=2;
                if(maxi == (double)l){ans--;}
            }
        }
    }
    cout<<ans;

}


#include <bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define M 1000000007
#define M2 998244353
#define ll long long
#define pll pair<long,long>
#define REP(i,a,b) for(ll i=a;i<b;i++)
#define REPI(i,a,b) for(ll i=b-1;i>=a;i--)
#define ff first
#define ss second
#define pb push_back
#define db pop_back
#define mp make_pair
#define mt make_tuple
#define g(a,b) get<a>(b)
#define INF 1e18

#define o_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define o_setll tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>
//member functions :
//1. order_of_key(k) : number of elements strictly lesser than k
//2. find_by_order(k) : k-th element in the set

ll modI(ll a, ll m);
ll gcd(ll a, ll b);
ll powM(ll x, unsigned ll y, unsigned ll m);
void pairsort(int a[], int b[], int n);
void pairsortll(ll a[],ll b[],ll n);
ll logint(ll x,ll y);

ll gcd(ll x,ll y)
{
    if(x==0) return y;
    return gcd(y%x,x);
}

ll powM(ll x,ll y,ll m)
{
    if(y==0) return 1;
    ll p=powM(x,y/2,m)%m;
    p=(p*p)%m;
    return (y%2==0)?p:(x*p)%m;
}

ll modI(ll a, ll m)
{
   return powM(a, m-2, m);
}

void pairsort(int a[],int b[],int n)
{
    pair<int,int> v[n];
    REP(i,0,n)
    {
        v[i].ff=a[i];
        v[i].ss=b[i];
    }
    sort(v,v+n);
    REP(i,0,n)
    {
        a[i]=v[i].ff;
        b[i]=v[i].ss;
    }
}

void pairsortll(ll a[],ll b[],ll n)
{
    pair<ll,ll> v[n];
    REP(i,0,n)
    {
        v[i].ff=a[i];
        v[i].ss=b[i];
    }
    sort(v,v+n);
    REP(i,0,n)
    {
        a[i]=v[i].ff;
        b[i]=v[i].ss;
    }
}

ll logint(ll x,ll y)
{
    ll ans=0;
    ll a=1;
    for(ll i=0;i<=x;i++)
    {
        if(x<a)
        {
            return ans;
        }
        ans++;
        a*=y;
    }
    return -1;
}
ll dist[100001];
vector<pair<ll, ll> >v[100001];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    ll n, m, s;
    cin>>n>>m>>s;

    ll ar[m][3];
    REP(i, 0, m){
        ll x, y, w;
        cin>>x>>y>>w;
        ar[i][0] = x;
        ar[i][1] = y;
        ar[i][2] = w;
        v[x].pb({w, y});
        v[y].pb({w, x});
    }
    ll l;
    cin>>l;
    REP(i, 0, n+1){
        dist[i] = INF;
    }
    priority_queue< pair<ll, ll>, vector<pair<ll, ll> >, greater<pair<ll, ll> > >pq;
    dist[s] = 0;
    pq.push({0, s});
    while(!pq.empty()){
        ll a = pq.top().ff;
        ll b = pq.top().ss;
        pq.pop();
        if(a > dist[b]){continue;}
        for(auto x : v[b]){
            if(dist[b]+x.ff < dist[x.ss]){
                dist[x.ss] = dist[b]+x.ff;
                pq.push({dist[x.ss], x.ss});
            }
        }
    }
    //cout<<dist[3]<<endl;
    ll ans=0;
    REP(i, 1, n+1){
        if(dist[i] == l){ans++; //cout<<i<<" ";
        }
    }
    //cout<<endl;
    REP(i, 0, m){
        double mini = min((double)dist[ar[i][0]], (double)dist[ar[i][1]]);
        double maxi = max((double)dist[ar[i][0]], (double)dist[ar[i][1]]);
        double weight = (double)ar[i][2];
        double x = (maxi-mini+weight)/(2*weight);
        if(mini >= (double)l){continue;}
        if(maxi > (double)l){ans++;}
        else if(x > 0 && x < 1){
            //cout<<mini+x*weight<<endl;
            if(mini+x*weight == (double)l){ans++;}
            else if(mini+x*weight > (double)l){ans+=2;
                if(maxi == (double)l){ans--;}
                if(mini == (double)l){ans--;}
            }
        }
    }
    cout<<ans;

}


#include <bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define M 1000000007
#define M2 998244353
#define ll long long
#define pll pair<long,long>
#define REP(i,a,b) for(ll i=a;i<b;i++)
#define REPI(i,a,b) for(ll i=b-1;i>=a;i--)
#define ff first
#define ss second
#define pb push_back
#define db pop_back
#define mp make_pair
#define mt make_tuple
#define g(a,b) get<a>(b)
#define INF 1e18

#define o_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define o_setll tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>
//member functions :
//1. order_of_key(k) : number of elements strictly lesser than k
//2. find_by_order(k) : k-th element in the set

ll modI(ll a, ll m);
ll gcd(ll a, ll b);
ll powM(ll x, unsigned ll y, unsigned ll m);
void pairsort(int a[], int b[], int n);
void pairsortll(ll a[],ll b[],ll n);
ll logint(ll x,ll y);

ll gcd(ll x,ll y)
{
    if(x==0) return y;
    return gcd(y%x,x);
}

ll powM(ll x,ll y,ll m)
{
    if(y==0) return 1;
    ll p=powM(x,y/2,m)%m;
    p=(p*p)%m;
    return (y%2==0)?p:(x*p)%m;
}

ll modI(ll a, ll m)
{
   return powM(a, m-2, m);
}

void pairsort(int a[],int b[],int n)
{
    pair<int,int> v[n];
    REP(i,0,n)
    {
        v[i].ff=a[i];
        v[i].ss=b[i];
    }
    sort(v,v+n);
    REP(i,0,n)
    {
        a[i]=v[i].ff;
        b[i]=v[i].ss;
    }
}

void pairsortll(ll a[],ll b[],ll n)
{
    pair<ll,ll> v[n];
    REP(i,0,n)
    {
        v[i].ff=a[i];
        v[i].ss=b[i];
    }
    sort(v,v+n);
    REP(i,0,n)
    {
        a[i]=v[i].ff;
        b[i]=v[i].ss;
    }
}

ll logint(ll x,ll y)
{
    ll ans=0;
    ll a=1;
    for(ll i=0;i<=x;i++)
    {
        if(x<a)
        {
            return ans;
        }
        ans++;
        a*=y;
    }
    return -1;
}
ll dist[100001];
vector<pair<ll, ll> >v[100001];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    ll n, m, s;
    cin>>n>>m>>s;

    ll ar[m][3];
    REP(i, 0, m){
        ll x, y, w;
        cin>>x>>y>>w;
        ar[i][0] = x;
        ar[i][1] = y;
        ar[i][2] = w;
        v[x].pb({w, y});
        v[y].pb({w, x});
    }
    ll l;
    cin>>l;
    REP(i, 0, n+1){
        dist[i] = INF;
    }
    priority_queue< pair<ll, ll>, vector<pair<ll, ll> >, greater<pair<ll, ll> > >pq;
    dist[s] = 0;
    pq.push({0, s});
    while(!pq.empty()){
        ll a = pq.top().ff;
        ll b = pq.top().ss;
        pq.pop();
        if(a > dist[b]){continue;}
        for(auto x : v[b]){
            if(dist[b]+x.ff < dist[x.ss]){
                dist[x.ss] = dist[b]+x.ff;
                pq.push({dist[x.ss], x.ss});
            }
        }
    }
    //cout<<dist[3]<<endl;
    ll ans=0;
    REP(i, 1, n+1){
        if(dist[i] == l){ans++;}
    }
    REP(i, 0, m){
        double mini = min((double)dist[ar[i][0]], (double)dist[ar[i][1]]);
        double maxi = max((double)dist[ar[i][0]], (double)dist[ar[i][1]]);
        double weight = (double)ar[i][2];
        double x = (maxi-mini+weight)/(2*weight);
        if(mini + x*weight == maxi){continue;}
        if(mini+x*weight > (double)l){ans+=2;
        }
        else if(mini+x*weight == (double)l){ans++;
        }
        if(dist[ar[i][0]] == l){ans--;}
        if(dist[ar[i][1]] == l){ans--;}
    }
    //cout<<endl;
    cout<<ans;

}


// Best practice

#include<bits/stdc++.h>

#define int         long long
#define pb          push_back
#define pf          emplace_front
#define all(a)      (a).begin(),(a).end()
#define rall(a)     (a).rbegin(),(a).rend()
#define pii 		pair<int,int>
#define psi 		pair<string,int>
#define vi 			vector<int>
#define vpii  		vector<pii>
#define vvi 		vector<vi>
#define sz(x)	    (int)(x).size()
#define x           first
#define y           second
#define endl        '\n'
#define tezz        ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define MOD         1000000007
#define hell        998244353
#define prec(n) 	fixed<<setprecision(n)
#define in(x) 		scanf("%d", &x)
#define echo(x)		printf("%d", x)
#define inf 		(int)(1e18)
#define ini(a, i) 	memset(a, i, sizeof(a))
#define output(x)   cout << (x ? "YES" : "NO")<<endl;
using namespace std;

#define debug(vec) cout<<(#vec)<<" : [ "; for (auto& i: vec) cout<<i<<" "; cout<< "]" << endl
#define debugp(vec) cout<<(#vec)<<" : [ "; for (auto& i: vec) cout<<"("<<i.x<<","<<i.y<<")"<<" "; cout<< "]" << endl
#define trace(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args);cout << endl; }
void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
    cout << "[" << *it << ": " << a << "]\t";
    err(++it, args...);
}

// const int dx[4] = { -1, 1, 0, 0};
// const int dy[4] = {0, 0, -1, 1};
// int dX[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
// int dY[] = { -1, 0, 1, -1, 1, -1, 0, 1 };

// Code from Here -------------------------------------------------------------------------------

const int nax=1e5+5;
vector<vpii> adj;
int d[nax];

void dijkstra(int s, int n) {
  fill(d, d + n, INT_MAX);
  d[s] = 0;
  priority_queue<pii, vector<pii>, greater<pii> > Q;
  Q.push(pii(d[s], s));
  while (!Q.empty()) {
    pii top = Q.top();
    Q.pop();
    int dd = top.first, u = top.second;
    if (dd > d[u]) continue;
    for (vector<pii>::iterator it = adj[u].begin(); it != adj[u].end(); ++it) {
      int v = it->first, cost = it->second;
      if (d[v] > d[u] + cost) {
        d[v] = d[u] + cost;
        Q.push(pii(d[v], v));
      }
    }
  }
}

signed main() {
	tezz

// #ifndef ONLINE_JUDGE
// 	freopen("input.txt", "r", stdin);
// 	freopen("output.txt", "w", stdout);
// #endif

	int n,m,k,p,q,w;
	cin >> n >> m >> k;
	k--;
	adj = vector<vpii> (n);
	for(int i=0; i<m; i++){
		cin >> p >> q >> w;
		p--;
		q--;
		adj[p].pb({q,w});
		adj[q].pb({p,w});
	}
	int l;
	cin >> l;
	dijkstra(k, n);
	int ans=0;
	for(int i=0; i<n; i++){
		for(auto it: adj[i]){
			p=i;
			q=it.x;
			w=it.y;
			int c=0;
			if(d[p]<l && d[p]+w>l){
				// int y = l;
				// int yy = w-(l-d[p])+d[q];
				// if(yy>=y){
					ans++;
					c++;
				// }
			}
			// trace(d[p],d[q],w,ans);
			if(d[q]<l && d[q]+w>l){
				// int y = l;
				// int yy = w-(l-d[q])+d[p];
				// if(yy>=y){
					ans++;
					c++;
				// }
			}
			if(l-d[p] + l-d[q] == w && c==2)ans--;
		}
	}
	ans/=2;
	for(int i=0; i<n; i++){
		// trace(d[i]);
		if(d[i]==l)ans++;
	}
	cout << ans;

	return 0;
}


// Best practice

#include<bits/stdc++.h>

#define int         long long
#define pb          push_back
#define pf          emplace_front
#define all(a)      (a).begin(),(a).end()
#define rall(a)     (a).rbegin(),(a).rend()
#define pii 		pair<int,int>
#define psi 		pair<string,int>
#define vi 			vector<int>
#define vpii  		vector<pii>
#define vvi 		vector<vi>
#define sz(x)	    (int)(x).size()
#define x           first
#define y           second
#define endl        '\n'
#define tezz        ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define MOD         1000000007
#define hell        998244353
#define prec(n) 	fixed<<setprecision(n)
#define in(x) 		scanf("%d", &x)
#define echo(x)		printf("%d", x)
#define inf 		(int)(1e18)
#define ini(a, i) 	memset(a, i, sizeof(a))
#define output(x)   cout << (x ? "YES" : "NO")<<endl;
using namespace std;

#define debug(vec) cout<<(#vec)<<" : [ "; for (auto& i: vec) cout<<i<<" "; cout<< "]" << endl
#define debugp(vec) cout<<(#vec)<<" : [ "; for (auto& i: vec) cout<<"("<<i.x<<","<<i.y<<")"<<" "; cout<< "]" << endl
#define trace(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args);cout << endl; }
void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
    cout << "[" << *it << ": " << a << "]\t";
    err(++it, args...);
}

// const int dx[4] = { -1, 1, 0, 0};
// const int dy[4] = {0, 0, -1, 1};
// int dX[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
// int dY[] = { -1, 0, 1, -1, 1, -1, 0, 1 };

// Code from Here -------------------------------------------------------------------------------

const int nax=1e5+5;
vector<vpii> adj;
int d[nax];

void dijkstra(int s, int n) {
  fill(d, d + n, INT_MAX);
  d[s] = 0;
  priority_queue<pii, vector<pii>, greater<pii> > Q;
  Q.push(pii(d[s], s));
  while (!Q.empty()) {
    pii top = Q.top();
    Q.pop();
    int dd = top.first, u = top.second;
    if (dd > d[u]) continue;
    for (vector<pii>::iterator it = adj[u].begin(); it != adj[u].end(); ++it) {
      int v = it->first, cost = it->second;
      if (d[v] > d[u] + cost) {
        d[v] = d[u] + cost;
        Q.push(pii(d[v], v));
      }
    }
  }
}

signed main() {
	tezz

#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif

	int n,m,k,p,q,w;
	cin >> n >> m >> k;
	k--;
	adj = vector<vpii> (n);
	for(int i=0; i<m; i++){
		cin >> p >> q >> w;
		p--;
		q--;
		adj[p].pb({q,w});
		adj[q].pb({p,w});
	}
	int l;
	cin >> l;
	dijkstra(k, n);
	int ans=0;
	for(int i=0; i<n; i++){
		for(auto it: adj[i]){
			p=i;
			q=it.x;
			w=it.y;
			int c=0;
			if(d[p]<l && d[p]+w>l){
				int y = l;
				int yy = w-(l-d[p])+d[q];
				if(yy>=y){
					ans++;
					c++;
				}
			}
			// trace(d[p],d[q],w,ans);
			if(d[q]<l && d[q]+w>l){
				int y = l;
				int yy = w-(l-d[q])+d[p];
				if(yy>=y){
					ans++;
					c++;
				}
			}
			if(l-d[p] + l-d[q] == w && c==2)ans--;
		}
	}
	ans/=2;
	for(int i=0; i<n; i++){
		// trace(d[i]);
		if(d[i]==l)ans++;
	}
	cout << ans;

	return 0;
}


// Best practice

#include<bits/stdc++.h>

#define int         long long
#define pb          push_back
#define pf          emplace_front
#define all(a)      (a).begin(),(a).end()
#define rall(a)     (a).rbegin(),(a).rend()
#define pii 		pair<int,int>
#define psi 		pair<string,int>
#define vi 			vector<int>
#define vpii  		vector<pii>
#define vvi 		vector<vi>
#define sz(x)	    (int)(x).size()
#define x           first
#define y           second
#define endl        '\n'
#define tezz        ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define MOD         1000000007
#define hell        998244353
#define prec(n) 	fixed<<setprecision(n)
#define in(x) 		scanf("%d", &x)
#define echo(x)		printf("%d", x)
#define inf 		(int)(1e18)
#define ini(a, i) 	memset(a, i, sizeof(a))
#define output(x)   cout << (x ? "YES" : "NO")<<endl;
using namespace std;

#define debug(vec) cout<<(#vec)<<" : [ "; for (auto& i: vec) cout<<i<<" "; cout<< "]" << endl
#define debugp(vec) cout<<(#vec)<<" : [ "; for (auto& i: vec) cout<<"("<<i.x<<","<<i.y<<")"<<" "; cout<< "]" << endl
#define trace(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args);cout << endl; }
void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
    cout << "[" << *it << ": " << a << "]\t";
    err(++it, args...);
}

// const int dx[4] = { -1, 1, 0, 0};
// const int dy[4] = {0, 0, -1, 1};
// int dX[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
// int dY[] = { -1, 0, 1, -1, 1, -1, 0, 1 };

// Code from Here -------------------------------------------------------------------------------

const int nax=1e5+5;
vector<vpii> adj;
int d[nax];

void dijkstra(int s, int n) {
  fill(d, d + n, INT_MAX);
  d[s] = 0;
  priority_queue<pii, vector<pii>, greater<pii> > Q;
  Q.push(pii(d[s], s));
  while (!Q.empty()) {
    pii top = Q.top();
    Q.pop();
    int dd = top.first, u = top.second;
    if (dd > d[u]) continue;
    for (vector<pii>::iterator it = adj[u].begin(); it != adj[u].end(); ++it) {
      int v = it->first, cost = it->second;
      if (d[v] > d[u] + cost) {
        d[v] = d[u] + cost;
        Q.push(pii(d[v], v));
      }
    }
  }
}

signed main() {
	tezz

#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif

	int n,m,k,p,q,w;
	cin >> n >> m >> k;
	k--;
	adj = vector<vpii> (n);
	for(int i=0; i<m; i++){
		cin >> p >> q >> w;
		p--;
		q--;
		adj[p].pb({q,w});
		adj[q].pb({p,w});
	}
	int l;
	cin >> l;
	dijkstra(k, n);
	int ans=0;
	for(int i=0; i<n; i++){
		for(auto it: adj[i]){
			p=i;
			q=it.x;
			w=it.y;
			if(d[p]<l && d[p]+w>l){
				ans++;
			}
			if(d[q]<l && d[q]+w>l){
				ans++;
			}
			if(l-d[p] + l-d[q] == w && d[p]<l && d[q]<l)ans--;
			// trace(p,q,ans);
		}
	}
	ans/=2;
	for(int i=0; i<n; i++){
		// trace(d[i]);
		if(d[i]==l)ans++;
	}
	cout << ans;

	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <cmath>
#include <climits>
#include <queue>
#include <string>
using namespace std;
typedef long long ll;

const int INF = INT_MAX;
// const long long INF = LLONG_MAX;

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);

    int n, m, s;
    cin >> n >> m >> s;
    s--;
    vector<vector<pair<int, int>>> g(n);
    vector<int> d(n, INF);
    vector<int> p(n);

    for (int i = 0; i < m; i++)
    {
        int a, b, w;
        cin >> a >> b >> w;
        g[a - 1].push_back(make_pair(b - 1, w));
        g[b - 1].push_back(make_pair(a - 1, w));
    }
    int l;
    cin >> l;
    d[s] = 0;

    set<pair<int, int>> setik;
    setik.insert(make_pair(d[s], s));
    vector<vector<bool>> used(n, vector<bool>(m));
    int ans = 0;
    while (!setik.empty())
    {
        int v = setik.begin()->second;
        setik.erase(setik.begin());

        for (auto e : g[v])
        {
            if (d[v] + e.second < d[e.first])
            {
                setik.erase(make_pair(d[e.first], e.first));
                // used[p[e.first]][e.first] = 0;
                // used[e.first][p[e.first]] = 0;
                // used[v][e.first] = 1;
                // used[e.first][v] = 1;

                d[e.first] = d[v] + e.second;
                p[e.first] = v;
                setik.insert(make_pair(d[e.first], e.first));
            }
        }
    }
    // for (int i : d)
    //     cout << i << ' ';
    // cout << endl;
    for (int v = 0; v < n; v++)
    {
        for (auto e : g[v])
        {
            // if (!used[v][e.first] && !used[e.first][v])
            // {
                // cout << "v = " << v + 1<< " d[v] = " << d[v] << endl;
                // cout << "e.first = " << e.first + 1<< " d[e.first] = " << d[e.first] << endl;
                int len = e.second;
                if (d[v] < l && d[v] + len > l && len - (l - d[v]) + d[e.first] > l)
                {
                    // cout << 1 << endl;
                    ans++;
                }
                if (d[e.first] < l && d[e.first] + len > l && len - (l - d[e.first]) + d[v] > l)
                {
                    // cout << 2 << endl;
                    ans++;
                }
                if (d[v] < l && d[e.first] < l && d[v] + d[e.first] + len == l * 2)
                {
                    // cout << 3 << endl;
                    ans++;
                }
                // cout << endl;

                used[v][e.first] = 1;
                used[e.first][v] = 1;
            // }
        }
    }
    ans /= 2;

    for (int i : d)
    {
        if (i == l)
            ans++;
    }
    cout << ans;

    return 0;
}