#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 v = 0; v < n; v++)
    {
        for (auto e : g[v])
        {
            if (!used[v][e.first] && !used[e.first][v])
            {
                int len = e.second;
                if (d[v] < l && d[v] + len > l && len - (l - d[v]) + d[e.first] > l)
                    ans++;
                if (d[e.first] < l && d[e.first] + len > l && len - (l - d[e.first]) + d[v] > l)
                    ans++;
                if (d[v] < l && d[e.first] < l && d[v] + d[e.first] + len == l * 2)
                    ans++;

                used[v][e.first] = 1;
                used[e.first][v] = 1;
            }
        }
    }

    for (int i : d)
    {
        if (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;
}


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


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

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

    return 0;
}


/*
	Nitesh Kumar (codeshaker)
*/

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <map>
#include <functional>
#include <set>
#include <queue>
#include <stack>
#include <deque>
#include <vector>
#include <string>
#include <bitset>
#include <climits>
#include <complex>
using namespace std;

#define MAXN 100005
#define ll long long
#define pii pair<int,int>
#define pip pair<int,pii>
#define pci pair<char,int>

vector<pii> g[MAXN];
vector<pip> edge;
int d[MAXN];

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

	int n, m, s, l;
	cin >> n >> m >> s;

	for (int i = 0; i < m; i++)
	{
		int u, v, w;
		cin >> u >> v >> w;
		g[u].push_back(pii(v, w));
		g[v].push_back(pii(u, w));
		edge.push_back(pip(w,pii(u, v)));
	}

	cin >> l;

	for (int i = 0; i <= n; i++)
	{
		d[i] = 1e9;
	}

	priority_queue<pii, vector<pii>, greater<pii>> Q;

	Q.push(pii(0, s));
	d[s] = 0;

	while (!Q.empty())
	{
		int u = Q.top().second;
		Q.pop();

		for (int i = 0; i < g[u].size(); i++)
		{
			int v = g[u][i].first;
			int w = g[u][i].second;
			if (d[v] > (w + d[u]))
			{
				d[v] = w + d[u];
				Q.push(pii(d[v], v));
			}
		}
	}

	int ans = 0;

	// Cacluate proper nodes at dance l

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

	// Calculate for edges
	for (int i = 0; i < edge.size(); i++)
	{
		int u = edge[i].second.first, v = edge[i].second.second, w = edge[i].first;

		if (d[u]<l && (l - d[u] < w) && ((w - (l - d[u]) + d[v])>l))
			ans++;

		if (d[v]<l && (l - d[v] < w) && ((w - (l - d[v]) + d[u])>l))
			ans++;

		if (d[u]<l && d[v]<l && (w + d[u] + d[v]) == 2*l)
			ans++;
	}

	cout << ans;

	return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <iostream>
#include <unordered_set>
using namespace std;

// A structure to represent a node in adjacency list
struct AdjListNode
{
	int dest;
	int weight;
	struct AdjListNode* next;
};

// A structure to represent an adjacency list
struct AdjList
{
	struct AdjListNode* head; // pointer to head node of list
};

// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be V (number of vertices in graph)
struct Graph
{
	int V;
	struct AdjList* array;
};

// A utility function to create a new adjacency list node
struct AdjListNode* newAdjListNode(int dest, int weight)
{
	struct AdjListNode* newNode =
		(struct AdjListNode*) malloc(sizeof(struct AdjListNode));
	newNode->dest = dest;
	newNode->weight = weight;
	newNode->next = NULL;
	return newNode;
}

// A utility function that creates a graph of V vertices
struct Graph* createGraph(int V)
{
	struct Graph* graph = (struct Graph*) malloc(sizeof(struct Graph));
	graph->V = V;

	// Create an array of adjacency lists. Size of array will be V
	graph->array = (struct AdjList*) malloc(V * sizeof(struct AdjList));

	// Initialize each adjacency list as empty by making head as NULL
	for (int i = 0; i < V; ++i)
		graph->array[i].head = NULL;

	return graph;
}

// Adds an edge to an undirected graph
void addEdge(struct Graph* graph, int src, int dest, int weight)
{
	// Add an edge from src to dest. A new node is added to the adjacency
	// list of src. The node is added at the beginning
	struct AdjListNode* newNode = newAdjListNode(dest, weight);
	newNode->next = graph->array[src].head;
	graph->array[src].head = newNode;

	// Since graph is undirected, add an edge from dest to src also
	newNode = newAdjListNode(src, weight);
	newNode->next = graph->array[dest].head;
	graph->array[dest].head = newNode;
}

// Structure to represent a min heap node
struct MinHeapNode
{
	int v;
	int dist;
};

// Structure to represent a min heap
struct MinHeap
{
	int size;	 // Number of heap nodes present currently
	int capacity; // Capacity of min heap
	int* pos;	 // This is needed for decreaseKey()
	struct MinHeapNode** array;
};

// A utility function to create a new Min Heap Node
struct MinHeapNode* newMinHeapNode(int v, int dist)
{
	struct MinHeapNode* minHeapNode =
		(struct MinHeapNode*) malloc(sizeof(struct MinHeapNode));
	minHeapNode->v = v;
	minHeapNode->dist = dist;
	return minHeapNode;
}

// A utility function to create a Min Heap
struct MinHeap* createMinHeap(int capacity)
{
	struct MinHeap* minHeap =
		(struct MinHeap*) malloc(sizeof(struct MinHeap));
	minHeap->pos = (int*)malloc(capacity * sizeof(int));
	minHeap->size = 0;
	minHeap->capacity = capacity;
	minHeap->array =
		(struct MinHeapNode**) malloc(capacity * sizeof(struct MinHeapNode*));
	return minHeap;
}

// A utility function to swap two nodes of min heap. Needed for min heapify
void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b)
{
	struct MinHeapNode* t = *a;
	*a = *b;
	*b = t;
}

// A standard function to heapify at given idx
// This function also updates position of nodes when they are swapped.
// Position is needed for decreaseKey()
void minHeapify(struct MinHeap* minHeap, int idx)
{
	int smallest, left, right;
	smallest = idx;
	left = 2 * idx + 1;
	right = 2 * idx + 2;

	if (left < minHeap->size &&
		minHeap->array[left]->dist < minHeap->array[smallest]->dist)
		smallest = left;

	if (right < minHeap->size &&
		minHeap->array[right]->dist < minHeap->array[smallest]->dist)
		smallest = right;

	if (smallest != idx)
	{
		// The nodes to be swapped in min heap
		MinHeapNode* smallestNode = minHeap->array[smallest];
		MinHeapNode* idxNode = minHeap->array[idx];

		// Swap positions
		minHeap->pos[smallestNode->v] = idx;
		minHeap->pos[idxNode->v] = smallest;

		// Swap nodes
		swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);

		minHeapify(minHeap, smallest);
	}
}

// A utility function to check if the given minHeap is ampty or not
int isEmpty(struct MinHeap* minHeap)
{
	return minHeap->size == 0;
}

// Standard function to extract minimum node from heap
struct MinHeapNode* extractMin(struct MinHeap* minHeap)
{
	if (isEmpty(minHeap))
		return NULL;

	// Store the root node
	struct MinHeapNode* root = minHeap->array[0];

	// Replace root node with last node
	struct MinHeapNode* lastNode = minHeap->array[minHeap->size - 1];
	minHeap->array[0] = lastNode;

	// Update position of last node
	minHeap->pos[root->v] = minHeap->size - 1;
	minHeap->pos[lastNode->v] = 0;

	// Reduce heap size and heapify root
	--minHeap->size;
	minHeapify(minHeap, 0);

	return root;
}

// Function to decreasy dist value of a given vertex v. This function
// uses pos[] of min heap to get the current index of node in min heap
void decreaseKey(struct MinHeap* minHeap, int v, int dist)
{
	// Get the index of v in heap array
	int i = minHeap->pos[v];

	// Get the node and update its dist value
	minHeap->array[i]->dist = dist;

	// Travel up while the complete tree is not hepified.
	// This is a O(Logn) loop
	while (i && minHeap->array[i]->dist < minHeap->array[(i - 1) / 2]->dist)
	{
		// Swap this node with its parent
		minHeap->pos[minHeap->array[i]->v] = (i - 1) / 2;
		minHeap->pos[minHeap->array[(i - 1) / 2]->v] = i;
		swapMinHeapNode(&minHeap->array[i], &minHeap->array[(i - 1) / 2]);

		// move to parent index
		i = (i - 1) / 2;
	}
}

// A utility function to check if a given vertex
// 'v' is in min heap or not
bool isInMinHeap(struct MinHeap* minHeap, int v)
{
	if (minHeap->pos[v] < minHeap->size)
		return true;
	return false;
}

// A utility function used to print the solution
void printArr(int dist[], int n)
{
	printf("Vertex Distance from Source\n");
	for (int i = 0; i < n; ++i)
		printf("%d \t\t %d\n", i, dist[i]);
}

// The main function that calulates distances of shortest paths from src to all
// vertices. It is a O(ELogV) function
int* dijkstra(struct Graph* graph, int src)
{
	int V = graph->V;// Get the number of vertices in graph
	int* dist = new int[V];	 // dist values used to pick minimum weight edge in cut

	// minHeap represents set E
	struct MinHeap* minHeap = createMinHeap(V);

	// Initialize min heap with all vertices. dist value of all vertices
	for (int v = 0; v < V; ++v)
	{
		dist[v] = INT_MAX;
		minHeap->array[v] = newMinHeapNode(v, dist[v]);
		minHeap->pos[v] = v;
	}

	// Make dist value of src vertex as 0 so that it is extracted first
	minHeap->array[src] = newMinHeapNode(src, dist[src]);
	minHeap->pos[src] = src;
	dist[src] = 0;
	decreaseKey(minHeap, src, dist[src]);

	// Initially size of min heap is equal to V
	minHeap->size = V;

	// In the followin loop, min heap contains all nodes
	// whose shortest distance is not yet finalized.
	while (!isEmpty(minHeap))
	{
		// Extract the vertex with minimum distance value
		struct MinHeapNode* minHeapNode = extractMin(minHeap);
		int u = minHeapNode->v; // Store the extracted vertex number

		// Traverse through all adjacent vertices of u (the extracted
		// vertex) and update their distance values
		struct AdjListNode* pCrawl = graph->array[u].head;
		while (pCrawl != NULL)
		{
			int v = pCrawl->dest;

			// If shortest distance to v is not finalized yet, and distance to v
			// through u is less than its previously calculated distance
			if (isInMinHeap(minHeap, v) && dist[u] != INT_MAX &&
				pCrawl->weight + dist[u] < dist[v])
			{
				dist[v] = dist[u] + pCrawl->weight;

				// update distance value in min heap also
				decreaseKey(minHeap, v, dist[v]);
			}
			pCrawl = pCrawl->next;
		}
	}

	return dist;
}

class Edge {
public:
	int node1, node2, distance;
	Edge(int n1, int n2, int d) {
		this->node1 = n1;
		this->node2 = n2;
		this->distance = d;
	}
};

// Driver program to test above functions
int main()
{
	// create the graph given in above fugure
	int nodes;
	int edges;
	int source;
	int node1;
	int node2;
	int distance;

	cin >> nodes;
	cin >> edges;
	cin >> source;

	source--;

	struct Graph* graph = createGraph(nodes);

	Edge** edgesList = new Edge*[edges];

	for (int i = 0; i < edges; i++) {
		cin >> node1;
		cin >> node2;
		cin >> distance;

		addEdge(graph, node1 - 1, node2 - 1, distance);
		edgesList[i] = new Edge(node1-1, node2-1, distance);
	}

	int exactDistance;
	cin >> exactDistance;

	int* dist = dijkstra(graph, 0);
	unordered_set <int> visited;

	int counter = 0;

	for (int i = 0; i < edges; i++) {
		int node1 = edgesList[i]->node1;
		int node2 = edgesList[i]->node2;
		int distance = edgesList[i]->distance;

		if (dist[node1] == exactDistance && visited.find(node1) == visited.end()) {
			counter++;
			visited.insert(node1);
		}

		if (dist[node2] == exactDistance && visited.find(node2) == visited.end()) {
			counter++;
			visited.insert(node2);
		}

		if (exactDistance > dist[node1] && exactDistance < dist[node1] + distance) {
			int leftover = dist[node1] + distance - exactDistance;
			if (leftover + dist[node2] >= exactDistance) {
				if (leftover + dist[node2] >= exactDistance) {
					counter++;
				}
			}
		}

		if (exactDistance > dist[node2] && exactDistance < dist[node2] + distance) {
			int leftover = dist[node2] + distance - exactDistance;
			if (leftover + dist[node1] >= exactDistance) {
				if (leftover + dist[node1] > exactDistance) {
					counter++;
				}
			}
		}
	}

	cout << counter << endl;

	return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <iostream>
#include <unordered_set>
using namespace std;

// A structure to represent a node in adjacency list
struct AdjListNode
{
	int dest;
	int weight;
	struct AdjListNode* next;
};

// A structure to represent an adjacency list
struct AdjList
{
	struct AdjListNode* head; // pointer to head node of list
};

// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be V (number of vertices in graph)
struct Graph
{
	int V;
	struct AdjList* array;
};

// A utility function to create a new adjacency list node
struct AdjListNode* newAdjListNode(int dest, int weight)
{
	struct AdjListNode* newNode =
		(struct AdjListNode*) malloc(sizeof(struct AdjListNode));
	newNode->dest = dest;
	newNode->weight = weight;
	newNode->next = NULL;
	return newNode;
}

// A utility function that creates a graph of V vertices
struct Graph* createGraph(int V)
{
	struct Graph* graph = (struct Graph*) malloc(sizeof(struct Graph));
	graph->V = V;

	// Create an array of adjacency lists. Size of array will be V
	graph->array = (struct AdjList*) malloc(V * sizeof(struct AdjList));

	// Initialize each adjacency list as empty by making head as NULL
	for (int i = 0; i < V; ++i)
		graph->array[i].head = NULL;

	return graph;
}

// Adds an edge to an undirected graph
void addEdge(struct Graph* graph, int src, int dest, int weight)
{
	// Add an edge from src to dest. A new node is added to the adjacency
	// list of src. The node is added at the beginning
	struct AdjListNode* newNode = newAdjListNode(dest, weight);
	newNode->next = graph->array[src].head;
	graph->array[src].head = newNode;

	// Since graph is undirected, add an edge from dest to src also
	newNode = newAdjListNode(src, weight);
	newNode->next = graph->array[dest].head;
	graph->array[dest].head = newNode;
}

// Structure to represent a min heap node
struct MinHeapNode
{
	int v;
	int dist;
};

// Structure to represent a min heap
struct MinHeap
{
	int size;	 // Number of heap nodes present currently
	int capacity; // Capacity of min heap
	int* pos;	 // This is needed for decreaseKey()
	struct MinHeapNode** array;
};

// A utility function to create a new Min Heap Node
struct MinHeapNode* newMinHeapNode(int v, int dist)
{
	struct MinHeapNode* minHeapNode =
		(struct MinHeapNode*) malloc(sizeof(struct MinHeapNode));
	minHeapNode->v = v;
	minHeapNode->dist = dist;
	return minHeapNode;
}

// A utility function to create a Min Heap
struct MinHeap* createMinHeap(int capacity)
{
	struct MinHeap* minHeap =
		(struct MinHeap*) malloc(sizeof(struct MinHeap));
	minHeap->pos = (int*)malloc(capacity * sizeof(int));
	minHeap->size = 0;
	minHeap->capacity = capacity;
	minHeap->array =
		(struct MinHeapNode**) malloc(capacity * sizeof(struct MinHeapNode*));
	return minHeap;
}

// A utility function to swap two nodes of min heap. Needed for min heapify
void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b)
{
	struct MinHeapNode* t = *a;
	*a = *b;
	*b = t;
}

// A standard function to heapify at given idx
// This function also updates position of nodes when they are swapped.
// Position is needed for decreaseKey()
void minHeapify(struct MinHeap* minHeap, int idx)
{
	int smallest, left, right;
	smallest = idx;
	left = 2 * idx + 1;
	right = 2 * idx + 2;

	if (left < minHeap->size &&
		minHeap->array[left]->dist < minHeap->array[smallest]->dist)
		smallest = left;

	if (right < minHeap->size &&
		minHeap->array[right]->dist < minHeap->array[smallest]->dist)
		smallest = right;

	if (smallest != idx)
	{
		// The nodes to be swapped in min heap
		MinHeapNode* smallestNode = minHeap->array[smallest];
		MinHeapNode* idxNode = minHeap->array[idx];

		// Swap positions
		minHeap->pos[smallestNode->v] = idx;
		minHeap->pos[idxNode->v] = smallest;

		// Swap nodes
		swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);

		minHeapify(minHeap, smallest);
	}
}

// A utility function to check if the given minHeap is ampty or not
int isEmpty(struct MinHeap* minHeap)
{
	return minHeap->size == 0;
}

// Standard function to extract minimum node from heap
struct MinHeapNode* extractMin(struct MinHeap* minHeap)
{
	if (isEmpty(minHeap))
		return NULL;

	// Store the root node
	struct MinHeapNode* root = minHeap->array[0];

	// Replace root node with last node
	struct MinHeapNode* lastNode = minHeap->array[minHeap->size - 1];
	minHeap->array[0] = lastNode;

	// Update position of last node
	minHeap->pos[root->v] = minHeap->size - 1;
	minHeap->pos[lastNode->v] = 0;

	// Reduce heap size and heapify root
	--minHeap->size;
	minHeapify(minHeap, 0);

	return root;
}

// Function to decreasy dist value of a given vertex v. This function
// uses pos[] of min heap to get the current index of node in min heap
void decreaseKey(struct MinHeap* minHeap, int v, int dist)
{
	// Get the index of v in heap array
	int i = minHeap->pos[v];

	// Get the node and update its dist value
	minHeap->array[i]->dist = dist;

	// Travel up while the complete tree is not hepified.
	// This is a O(Logn) loop
	while (i && minHeap->array[i]->dist < minHeap->array[(i - 1) / 2]->dist)
	{
		// Swap this node with its parent
		minHeap->pos[minHeap->array[i]->v] = (i - 1) / 2;
		minHeap->pos[minHeap->array[(i - 1) / 2]->v] = i;
		swapMinHeapNode(&minHeap->array[i], &minHeap->array[(i - 1) / 2]);

		// move to parent index
		i = (i - 1) / 2;
	}
}

// A utility function to check if a given vertex
// 'v' is in min heap or not
bool isInMinHeap(struct MinHeap* minHeap, int v)
{
	if (minHeap->pos[v] < minHeap->size)
		return true;
	return false;
}

// A utility function used to print the solution
void printArr(int dist[], int n)
{
	printf("Vertex Distance from Source\n");
	for (int i = 0; i < n; ++i)
		printf("%d \t\t %d\n", i, dist[i]);
}

// The main function that calulates distances of shortest paths from src to all
// vertices. It is a O(ELogV) function
int* dijkstra(struct Graph* graph, int src)
{
	int V = graph->V;// Get the number of vertices in graph
	int* dist = new int[V];	 // dist values used to pick minimum weight edge in cut

	// minHeap represents set E
	struct MinHeap* minHeap = createMinHeap(V);

	// Initialize min heap with all vertices. dist value of all vertices
	for (int v = 0; v < V; ++v)
	{
		dist[v] = INT_MAX;
		minHeap->array[v] = newMinHeapNode(v, dist[v]);
		minHeap->pos[v] = v;
	}

	// Make dist value of src vertex as 0 so that it is extracted first
	minHeap->array[src] = newMinHeapNode(src, dist[src]);
	minHeap->pos[src] = src;
	dist[src] = 0;
	decreaseKey(minHeap, src, dist[src]);

	// Initially size of min heap is equal to V
	minHeap->size = V;

	// In the followin loop, min heap contains all nodes
	// whose shortest distance is not yet finalized.
	while (!isEmpty(minHeap))
	{
		// Extract the vertex with minimum distance value
		struct MinHeapNode* minHeapNode = extractMin(minHeap);
		int u = minHeapNode->v; // Store the extracted vertex number

		// Traverse through all adjacent vertices of u (the extracted
		// vertex) and update their distance values
		struct AdjListNode* pCrawl = graph->array[u].head;
		while (pCrawl != NULL)
		{
			int v = pCrawl->dest;

			// If shortest distance to v is not finalized yet, and distance to v
			// through u is less than its previously calculated distance
			if (isInMinHeap(minHeap, v) && dist[u] != INT_MAX &&
				pCrawl->weight + dist[u] < dist[v])
			{
				dist[v] = dist[u] + pCrawl->weight;

				// update distance value in min heap also
				decreaseKey(minHeap, v, dist[v]);
			}
			pCrawl = pCrawl->next;
		}
	}

	return dist;
}

class Edge {
public:
	int node1, node2, distance;
	Edge(int n1, int n2, int d) {
		this->node1 = n1;
		this->node2 = n2;
		this->distance = d;
	}
};

int main()
{
	int nodes;
	int edges;
	int source;
	int node1;
	int node2;
	int distance;

	cin >> nodes;
	cin >> edges;
	cin >> source;

	source--;

	struct Graph* graph = createGraph(nodes);

	Edge** edgesList = new Edge*[edges];

	for (int i = 0; i < edges; i++) {
		cin >> node1;
		cin >> node2;
		cin >> distance;

		addEdge(graph, node1 - 1, node2 - 1, distance);
		edgesList[i] = new Edge(node1-1, node2-1, distance);
	}

	int exactDistance;
	cin >> exactDistance;

	int* dist = dijkstra(graph, source);
	unordered_set <int> visited;

	int counter = 0;

	for (int i = 0; i < edges; i++) {
		int node1 = edgesList[i]->node1;
		int node2 = edgesList[i]->node2;
		int distance = edgesList[i]->distance;

		if (dist[node1] == exactDistance && visited.find(node1) == visited.end()) {
			counter++;
			visited.insert(node1);
		}

		if (dist[node2] == exactDistance && visited.find(node2) == visited.end()) {
			counter++;
			visited.insert(node2);
		}

		if (exactDistance > dist[node1] && exactDistance < dist[node1] + distance) {
			int leftover = dist[node1] + distance - exactDistance;
			if (leftover + dist[node2] >= exactDistance) {
				if (leftover + dist[node2] >= exactDistance) {
					counter++;
				}
			}
		}

		if (exactDistance > dist[node2] && exactDistance < dist[node2] + distance) {
			int leftover = dist[node2] + distance - exactDistance;
			if (leftover + dist[node1] >= exactDistance) {
				if (leftover + dist[node1] > exactDistance) {
					counter++;
				}
			}
		}
	}

	cout << counter << endl;

	return 0;
}


#define _CRT_SECURE_NO_DEPRECATE
#define _USE_MATH_DEFINES

#include <utility>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <stack>

using namespace std;

typedef long long int64;
#define INF 1234567890
#define prime 999979
#define FOR(a, b) for(int a = 0; a < b; ++a)
#define eps 1e-7

int n, m, s, d[100001], res = 0, r2 = 0, l;
vector <vector <pair <int, int> > > v;
set <pair<int, int> > q;

void dijkstra(int s)
{
    if (q.empty()) return;
    FOR(i, v[s].size())
        if (d[v[s][i].first] == -1) d[v[s][i].first] = d[s] + v[s][i].second;
            else d[v[s][i].first] = min(d[v[s][i].first], d[s] + v[s][i].second);
    int v = q.begin()->second;
    q.erase(q.begin());
    dijkstra(v);
}

int main()
{
    //freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
    scanf("%d%d%d/n", &n, &m, &s);
    --s;
    v.resize(n);
    FOR(i, m)
    {
        int x, y, w;
        scanf("%d%d%d", &x, &y, &w);
        --x; --y;
        v[x].push_back(make_pair(y, w));
        v[y].push_back(make_pair(x, w));
    }
    scanf("%d", &l);
    memset(d, -1, sizeof d);
    d[s] = 0;
    q.insert(make_pair(d[s], s));
    dijkstra(s);
    FOR(i, n)
        if (d[i] == l) ++res;
    FOR(i, n)
        FOR(j, v[i].size())
        {
            if (d[i] < l && d[i] + v[i][j].second > l && v[i][j].second - (l - d[i]) + d[v[i][j].first] > l) ++res;
            if (d[i] < l && d[v[i][j].first] < l && d[v[i][j].first] + d[i] + v[i][j].second == 2*l) ++r2;
        }
    cout << res + r2/2;
    return 0;
}


#define _CRT_SECURE_NO_DEPRECATE
#define _USE_MATH_DEFINES

#include <utility>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <stack>

using namespace std;

typedef long long int64;
#define INF 1234567890
#define prime 999979
#define FOR(a, b) for(int a = 0; a < b; ++a)
#define eps 1e-7

int n, m, s, d[100001], res = 0, r2 = 0, l;
vector <vector <pair <int, int> > > v;
set <pair<int, int> > q;

void dijkstra(int s)
{
    if (q.empty()) return;
    FOR(i, v[s].size())
        if (d[v[s][i].first] == -1)
            {
                d[v[s][i].first] = d[s] + v[s][i].second;
                q.insert(make_pair(d[v[s][i].first], v[s][i].first));
            }
            else
            {
                if (d[v[s][i].first] > d[s] + v[s][i].second)
                {
                    q.erase(make_pair(d[v[s][i].first], v[s][i].first));
                    d[v[s][i].first] = d[s] + v[s][i].second;
                    q.insert(make_pair(d[s] + v[s][i].second, v[s][i].first));
                }
            }
    q.erase(q.begin());
    int v = q.begin()->second;
    dijkstra(v);
}

int main()
{
    //freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
    scanf("%d%d%d/n", &n, &m, &s);
    --s;
    v.resize(n);
    FOR(i, m)
    {
        int x, y, w;
        scanf("%d%d%d", &x, &y, &w);
        --x; --y;
        v[x].push_back(make_pair(y, w));
        v[y].push_back(make_pair(x, w));
    }
    scanf("%d", &l);
    memset(d, -1, sizeof d);
    d[s] = 0;
    q.insert(make_pair(d[s], s));
    dijkstra(s);
    FOR(i, n)
        if (d[i] == l) ++res;
    FOR(i, n)
        FOR(j, v[i].size())
        {
            if (d[i] < l && d[i] + v[i][j].second > l && v[i][j].second - (l - d[i]) + d[v[i][j].first] > l) ++res;
            if (d[i] < l && d[v[i][j].first] < l && d[v[i][j].first] + d[i] + v[i][j].second == 2*l) ++r2;
        }
    cout << res + r2/2;
    return 0;
}


#define _CRT_SECURE_NO_DEPRECATE
#define _USE_MATH_DEFINES

#include <utility>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <stack>

using namespace std;

typedef long long int64;
#define INF 1234567890
#define prime 999979
#define FOR(a, b) for(int a = 0; a < b; ++a)
#define eps 1e-7

int n, m, s, d[100001], was[100001], res = 0, r2 = 0, l;
vector <vector <pair <int, int> > > v;

void dijkstra(int s)
{
    ++was[s];
    FOR(i, v[s].size())
        if (d[v[s][i].first] == -1) d[v[s][i].first] = d[s] + v[s][i].second;
            else d[v[s][i].first] = min(d[v[s][i].first], d[s] + v[s][i].second);
    int minn = -1;
    FOR(i, n)
        if (!was[i] && d[i] != -1)
            {
                if (minn == -1) minn = i;
                else
                    if (d[i] < d[minn]) minn = i;
            }
    if (minn != -1) dijkstra(minn);
}

int main()
{
    //freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
    scanf("%d%d%d/n", &n, &m, &s);
    --s;
    v.resize(n);
    FOR(i, m)
    {
        int x, y, w;
        scanf("%d%d%d", &x, &y, &w);
        --x; --y;
        v[x].push_back(make_pair(y, w));
        v[y].push_back(make_pair(x, w));
    }
    scanf("%d", &l);
    memset(d, -1, sizeof d);
    memset(was, 0, sizeof was);
    d[s] = 0;
    dijkstra(s);
    FOR(i, n)
        if (d[i] == l) ++res;
    FOR(i, n)
        FOR(j, v[i].size())
        {
            if (d[i] < l && d[i] + v[i][j].second > l && v[i][j].second - (l - d[i]) + d[v[i][j].first] > l) ++res;
            if (d[i] < l && d[v[i][j].first] < l && d[v[i][j].first] + d[i] + v[i][j].second == 2*l) ++r2;
        }
    cout << res + r2/2;
    return 0;
}


#define _CRT_SECURE_NO_DEPRECATE
#define _USE_MATH_DEFINES

#include <utility>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <stack>

using namespace std;

typedef long long int64;
#define INF 1234567890
#define prime 999979
#define FOR(a, b) for(int a = 0; a < b; ++a)
#define eps 1e-7

int n, m, s, d[100001], was[100001], res = 0, r2 = 0, l;
vector <vector <pair <int, int> > > v;

void dijkstra(int s)
{
    ++was[s];
    FOR(i, v[s].size())
        if (d[v[s][i].first] == -1) d[v[s][i].first] = d[s] + v[s][i].second;
            else d[v[s][i].first] = min(d[v[s][i].first], d[s] + v[s][i].second);
    int minn = -1;
    FOR(i, n)
        if (!was[i] && d[i] != -1)
            {
                if (minn == -1) minn = i;
                else
                    if (d[i] < d[minn]) minn = i;
            }
    if (minn != -1) dijkstra(minn);
}

int main()
{
    //freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
    scanf("%d%d%d/n", &n, &m, &s);
    --s;
    v.resize(n);
    FOR(i, m)
    {
        int x, y, w;
        cin >> x >> y >> w;
        --x; --y;
        v[x].push_back(make_pair(y, w));
        v[y].push_back(make_pair(x, w));
    }
    scanf("%d", &l);
    memset(d, -1, sizeof d);
    memset(was, 0, sizeof was);
    d[s] = 0;
    dijkstra(s);
    FOR(i, n)
        if (d[i] == l) ++res;
    FOR(i, n)
        FOR(j, v[i].size())
        {
            if (d[i] < l && d[i] + v[i][j].second > l && v[i][j].second - (l - d[i]) + d[v[i][j].first] > l) ++res;
            if (d[i] < l && d[v[i][j].first] < l && d[v[i][j].first] + d[i] + v[i][j].second == 2*l) ++r2;
        }
    cout << res + r2/2;
    return 0;
}


#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#define INF 1100000000
#define ll long long
#define size 3000001
using namespace std;

int n,m,s,u,v,w,next[size],len[size],head[size],to[size],cnt,l,d[100001],ans,from[size];
set<pair<int,int>> st;
bool used[100001];

void add(int u, int v, int w)
{
       cnt++;
      next[cnt]=head[u];
      from[cnt]=u;
      to[cnt]=v;
      len[cnt]=w;
      head[u]=cnt;
}

void dijkstra(int s)
{

    for (int i=1; i<=n; i++)
        if (i!=s) st.insert(make_pair(INF,i)),d[i]=INF;
    st.insert(make_pair(0,s));
    d[s]=0;

   for (int i=1; i<=n; i++)
   {
       set<pair<int,int>>::iterator p=st.begin();

       used[(*p).second]=true;
        int j=head[(*p).second];
      while (j!=0)
      {
        if (d[to[j]]>d[(*p).second]+len[j])
        {
            st.erase(make_pair(d[to[j]],to[j]));
            d[to[j]]=d[(*p).second]+len[j];
            st.insert(make_pair(d[to[j]],to[j]));
        }
          j=next[j];
      }
       st.erase(st.begin());
   }
}

int main()
{
       cin>>n>>m>>s;
     for (int i=1; i<=m; i++)
     {
         scanf("%d%d%d",&u,&v,&w);
         add(u,v,w);
         add(v,u,w);
     }

       cin>>l;

       dijkstra(s);

    for (int i=1; i<=cnt; i+=2)
    {
                if (d[to[i]]<l && d[from[i]]<l && d[to[i]]+d[from[i]]+len[i]==2*l) ans++;
                else
                {
                  if (d[from[i]]<l && l-d[from[i]]<len[i] && len[i]+(l-d[from[i]])+d[to[i]]>l) ans++;
                  if (d[to[i]]<l && l-d[to[i]]<len[i] && len[i]+(l-d[to[i]])+d[from[i]]>l) ans++;
                }
    }
    for (int i=1; i<=n; i++)
      if (d[i]==l) ans++;
    cout<<ans;
}


#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#define INF 1100000000
#define ll long long
#define size 300001
using namespace std;

int n,m,s,u,v,w,next[size],len[size],head[size],to[size],cnt,l,d[100001],ans;
set<pair<int,int>> st;
bool used[100001];

void add(int u, int v, int w)
{
       cnt++;
      next[cnt]=head[u];
      to[cnt]=v;
      len[cnt]=w;
      head[u]=cnt;
}

void dijkstra(int s)
{

    for (int i=1; i<=n; i++)
        if (i!=s) st.insert(make_pair(INF,i)),d[i]=INF;
    st.insert(make_pair(0,s));
    d[s]=0;

   for (int i=1; i<=n; i++)
   {
       set<pair<int,int>>::iterator p=st.begin();

       used[(*p).second]=true;
        int j=head[(*p).second];
      while (j!=0)
      {
        if (d[to[j]]>d[(*p).second]+len[j])
        {
            st.erase(make_pair(d[to[j]],to[j]));
            d[to[j]]=d[(*p).second]+len[j];
            st.insert(make_pair(d[to[j]],to[j]));
        }
          j=next[j];
      }
       st.erase(st.begin());
   }
}

int main()
{
       cin>>n>>m>>s;
     for (int i=1; i<=m; i++)
     {
         scanf("%d%d%d",&u,&v,&w);
         add(u,v,w);
         add(v,u,w);
     }
      cin>>l;
     for (int i=1; i<=cnt; i++)
         if (len[i]>l) ans+=len[i]/l;
     ans/=2;

      dijkstra(s);
    for (int i=1; i<=n; i++)
        if (d[i]==l) ans++;
    cout<<ans;
}


#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#define INF 1100000000
#define ll long long
#define size 3000001
using namespace std;

int n,m,s,u,v,w,next[size],len[size],head[size],to[size],cnt,l,d[100001],ans,from[size];
set<pair<int,int>> st;
bool used[100001];

void add(int u, int v, int w)
{
       cnt++;
      next[cnt]=head[u];
      from[cnt]=u;
      to[cnt]=v;
      len[cnt]=w;
      head[u]=cnt;
}

void dijkstra(int s)
{
     st.clear();
    for (int i=1; i<=n; i++)
        if (i!=s) st.insert(make_pair(INF,i)),d[i]=INF,used[i]=false;
    st.insert(make_pair(0,s));
    used[s]=false;
    d[s]=0;

   for (int i=1; i<=n; i++)
   {
       set<pair<int,int>>::iterator p=st.begin();

       used[(*p).second]=true;
        int j=head[(*p).second];
      while (j!=0)
      {
        if (d[to[j]]>d[(*p).second]+len[j])
        {
            st.erase(make_pair(d[to[j]],to[j]));
            d[to[j]]=d[(*p).second]+len[j];
            st.insert(make_pair(d[to[j]],to[j]));
        }
          j=next[j];
      }
       st.erase(st.begin());
   }
}

int main()
{
       cin>>n>>m>>s;
     for (int i=1; i<=m; i++)
     {
         scanf("%d%d%d",&u,&v,&w);
         add(u,v,w);
         add(v,u,w);
     }

       cin>>l;

       dijkstra(s);

    for (int i=1; i<=cnt; i+=2)
    {
                if (d[to[i]]<l && d[from[i]]<l && d[to[i]]+d[from[i]]+len[i]==2*l) ans++;
                else
                {
                  if (d[from[i]]<l && l-d[from[i]]<len[i] && len[i]-(l-d[from[i]])+d[to[i]]>l) ans++;
                  if (d[to[i]]<l && l-d[to[i]]<len[i] && len[i]-(l-d[to[i]])+d[from[i]]>l) ans++;
                }
    }
     for (int i=1; i<=n; i++)
         if (d[i]==l) ans++;
        cout<<ans;
}


#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#define INF 1100000000
#define ll long long
#define size 3000001
using namespace std;

int n,m,s,u,v,w,next[size],len[size],head[size],to[size],cnt,l,d[100001],ans,from[size];
set<pair<int,int>> st;
bool used[100001];

void add(int u, int v, int w)
{
       cnt++;
      next[cnt]=head[u];
      from[cnt]=u;
      to[cnt]=v;
      len[cnt]=w;
      head[u]=cnt;
}

void dijkstra(int s)
{

    for (int i=1; i<=n; i++)
        if (i!=s) st.insert(make_pair(INF,i)),d[i]=INF;
    st.insert(make_pair(0,s));
    d[s]=0;

   for (int i=1; i<=n; i++)
   {
       set<pair<int,int>>::iterator p=st.begin();

       used[(*p).second]=true;
        int j=head[(*p).second];
      while (j!=0)
      {
        if (d[to[j]]>d[(*p).second]+len[j])
        {
            st.erase(make_pair(d[to[j]],to[j]));
            d[to[j]]=d[(*p).second]+len[j];
            st.insert(make_pair(d[to[j]],to[j]));
        }
          j=next[j];
      }
       st.erase(st.begin());
   }
}

int main()
{
       cin>>n>>m>>s;
     for (int i=1; i<=m; i++)
     {
         scanf("%d%d%d",&u,&v,&w);
         add(u,v,w);
         add(v,u,w);
     }

       cin>>l;

       dijkstra(s);

    for (int i=1; i<=cnt; i++)
    {
                if (d[to[i]]<l && d[from[i]]<l && d[to[i]]+d[from[i]]+len[i]==2*l) ans++;
                else
                {
                if (d[from[i]]<l && l-d[from[i]]<len[i] && len[i]+(l-d[from[i]])+d[to[i]]>l) ans++;
                if (d[to[i]]<l && l-d[to[i]]<len[i] && len[i]+(l-d[to[i]])+d[from[i]]>l) ans++;
                }
    }
        ans/=2;
       for (int i=1; i<=n; i++)
        if (d[i]==l) ans++;
    cout<<ans;
}


#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#define INF 1100000000
#define ll long long
#define size 3000001
using namespace std;

int n,m,s,u,v,w,next[size],len[size],head[size],to[size],cnt,l,d[100001],ans,from[size];
set<pair<int,int>> st;
bool used[100001];

void add(int u, int v, int w)
{
       cnt++;
      next[cnt]=head[u];
      from[cnt]=u;
      to[cnt]=v;
      len[cnt]=w;
      head[u]=cnt;
}

void dijkstra(int s)
{
     st.clear();
    for (int i=1; i<=n; i++)
        if (i!=s) st.insert(make_pair(INF,i)),d[i]=INF,used[i]=false;
    st.insert(make_pair(0,s));
    used[s]=false;
    d[s]=0;

   for (int i=1; i<=n; i++)
   {
       set<pair<int,int>>::iterator p=st.begin();

       used[(*p).second]=true;
        int j=head[(*p).second];
      while (j!=0)
      {
        if (d[to[j]]>d[(*p).second]+len[j])
        {
            st.erase(make_pair(d[to[j]],to[j]));
            d[to[j]]=d[(*p).second]+len[j];
            st.insert(make_pair(d[to[j]],to[j]));
        }
          j=next[j];
      }
       st.erase(st.begin());
   }
}

int main()
{
       cin>>n>>m>>s;
     for (int i=1; i<=m; i++)
     {
         scanf("%d%d%d",&u,&v,&w);
         add(u,v,w);
         add(v,u,w);
     }

       cin>>l;

       dijkstra(s);

    for (int i=1; i<=cnt; i+=2)
    {
                if (d[to[i]]<l && d[from[i]]<l && d[to[i]]+d[from[i]]+len[i]==2*l) ans++;
                else
                {
                  if (d[from[i]]<l && l-d[from[i]]<len[i]) ans++;
                  if (d[to[i]]<l && l-d[to[i]]<len[i]) ans++;
                }
    }
     for (int i=1; i<=n; i++)
         if (d[i]==l) ans++;
        cout<<ans;
}


#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#define INF 1100000000
#define ll long long
#define size 3000001
using namespace std;

int n,m,s,u,v,w,next[size],len[size],head[size],to[size],cnt,l,d[100001],ans;
set<pair<int,int>> st;
bool used[100001];

void add(int u, int v, int w)
{
       cnt++;
      next[cnt]=head[u];
      to[cnt]=v;
      len[cnt]=w;
      head[u]=cnt;
}

void dijkstra(int s)
{

    for (int i=1; i<=n; i++)
        if (i!=s) st.insert(make_pair(INF,i)),d[i]=INF;
    st.insert(make_pair(0,s));
    d[s]=0;

   for (int i=1; i<=n; i++)
   {
       set<pair<int,int>>::iterator p=st.begin();

       used[(*p).second]=true;
        int j=head[(*p).second];
      while (j!=0)
      {
        if (d[to[j]]>d[(*p).second]+len[j])
        {
            st.erase(make_pair(d[to[j]],to[j]));
            d[to[j]]=d[(*p).second]+len[j];
            st.insert(make_pair(d[to[j]],to[j]));
        }
          j=next[j];
      }
       st.erase(st.begin());
   }
}

int main()
{
       cin>>n>>m>>s;
     for (int i=1; i<=m; i++)
     {
         scanf("%d%d%d",&u,&v,&w);
         add(u,v,w);
         add(v,u,w);
     }
      cin>>l;
     for (int i=1; i<=cnt; i++)
         if (len[i]>l) ans+=len[i]/l;
     ans/=2;

      dijkstra(s);
    for (int i=1; i<=n; i++)
        if (d[i]==l) ans++;
    cout<<ans;
}


//#pragma comment(linker,"/STACK:16777216") /*16Mb*/
//#pragma comment(linker,"/STACK:33554432") /*32Mb*/
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<numeric>
#include<sstream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<memory>
#include<string>
#include<vector>
#include<cctype>
#include<list>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;

typedef unsigned long long      ui64;
typedef long long               i64;
typedef vector<int>             VI;
typedef vector<bool>            VB;
typedef vector<VI>              VVI;
typedef vector<string>          VS;
typedef pair<int,int>           PII;
typedef map<string,int>         MSI;
typedef set<int>                SI;
typedef set<string>             SS;
typedef map<int,int>            MII;
typedef pair<double,double>     PDD;

#define PB                      push_back
#define MP                      make_pair
#define X                       first
#define Y                       second
#define FOR(i, a, b)            for(int i = (a); i < (b); ++i)
#define RFOR(i, a, b)           for(int i = (a) - 1; i >= (b); --i)
#define CLEAR(a, b)             memset(a, b, sizeof(a))
#define SZ(a)                   int((a).size())
#define ALL(a)                  (a).begin(), (a).end()
#define RALL(a)                 (a).rbegin(), (a).rend()

const i64 INF = 1000*1000*1000*100010;

int main()
{
    int n,m,s;
    cin >> n >> m >> s;
    vector< vector< pair<int,i64> > > g(n);
    vector< pair<PII,i64> > vertex(m);
    FOR(i,0,m) {
        int a, b, c;
        scanf("%d%d%d",&a,&b,&c);
        a--;b--;
        g[a].PB( MP(b,c) );
        g[b].PB( MP(a,c) );
        vertex[i] = MP(MP(a,b),c);
    }
    /*
    int L;
    cin >> L;

    queue<int> q;
    q.push(s);
    vector<i64> D(n,INF);
    D[s] = 0;
    set<PII> roads;
    while(!q.empty()) {
        int v = q.front();
        q.pop();
        int len = D[v];
        FOR(i,0,SZ(g[v])) {
            if( D[v] + g[v][i].Y <= D[ g[v][i].X ] ) {
                if( D[v] + g[v][i].Y >= L ) {
                    roads.insert( MP( min(v,g[v][i].X),max(v,g[v][i].X) ) );
                }
                D[ g[v][i].X ] = D[v] + g[v][i].Y;
                q.push( g[v][i].X );
            }
        }
    }
    cout << roads.size()<< endl;
    */

    s--;
    vector<i64> d (n, INF),  p(n);
    d[s] = 0;
    set < pair<i64,int> > q;
    q.insert (make_pair (d[s], s));
    while (!q.empty()) {
        int v = q.begin()->second;
        q.erase (q.begin());

        for (size_t j=0; j<g[v].size(); ++j) {
            i64 to = g[v][j].first,
                len = g[v][j].second;
            if (d[v] + len < d[to]) {
                q.erase (make_pair (d[to], to));
                d[to] = d[v] + len;
                p[to] = v;
                q.insert (make_pair (d[to], to));
            }
        }
    }

    i64 L;

    cin >> L;
    int ans = 0;
    /*FOR(i,0,n) {
        if( d[i]==L ) {
            ans ++;
        }
    }
    */

    FOR(i,0,m) {
        i64 A = d[vertex[i].X.X], B = d[vertex[i].X.Y];
        if( A > L && B > L )
            continue;

        if( A==L && B==L ) {
            continue;
        }

        if( A == L ) {
            //ans++;
            if( B + vertex[i].Y > L )
                ans++;
            continue;
        }

        if( B == L ) {
            //ans++;
            if( A + vertex[i].Y > L )
                ans++;
            continue;
        }

        i64 C = A + B + vertex[i].Y;

        if( A > L && B < L ) {
            if( B + vertex[i].Y  > L )
                ans++;
            continue;
        }

        if( A < L && B > L ) {
            if( A + vertex[i].Y  > L )
                ans++;
            continue;
        }

        if( C%2 ) {
            if( C/2 >= L )
                ans += 2;
        }
        else {
            if( C/2==L )
                ans++;
            else
                if( C/2 > L )
                    ans += 2;
        }
    }

    FOR(i,0,n)
        if( d[i]==L )
            ans++;
            //ans -= SZ(g[i])-1;

    cout << ans << endl;

    return 0;
}


//#pragma comment(linker,"/STACK:16777216") /*16Mb*/
//#pragma comment(linker,"/STACK:33554432") /*32Mb*/
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<numeric>
#include<sstream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<memory>
#include<string>
#include<vector>
#include<cctype>
#include<list>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;

typedef unsigned long long      ui64;
typedef long long               i64;
typedef vector<int>             VI;
typedef vector<bool>            VB;
typedef vector<VI>              VVI;
typedef vector<string>          VS;
typedef pair<int,int>           PII;
typedef map<string,int>         MSI;
typedef set<int>                SI;
typedef set<string>             SS;
typedef map<int,int>            MII;
typedef pair<double,double>     PDD;

#define PB                      push_back
#define MP                      make_pair
#define X                       first
#define Y                       second
#define FOR(i, a, b)            for(int i = (a); i < (b); ++i)
#define RFOR(i, a, b)           for(int i = (a) - 1; i >= (b); --i)
#define CLEAR(a, b)             memset(a, b, sizeof(a))
#define SZ(a)                   int((a).size())
#define ALL(a)                  (a).begin(), (a).end()
#define RALL(a)                 (a).rbegin(), (a).rend()

const i64 INF = 1000*1000*1000*100010;

int main()
{
    int n,m,s;
    cin >> n >> m >> s;
    vector< vector< pair<int,i64> > > g(n);
    vector< pair<PII,i64> > vertex(m);
    FOR(i,0,m) {
        int a, b, c;
        scanf("%d%d%d",&a,&b,&c);
        a--;b--;
        g[a].PB( MP(b,c) );
        g[b].PB( MP(a,c) );
        vertex[i] = MP(MP(a,b),c);
    }
    /*
    int L;
    cin >> L;

    queue<int> q;
    q.push(s);
    vector<i64> D(n,INF);
    D[s] = 0;
    set<PII> roads;
    while(!q.empty()) {
        int v = q.front();
        q.pop();
        int len = D[v];
        FOR(i,0,SZ(g[v])) {
            if( D[v] + g[v][i].Y <= D[ g[v][i].X ] ) {
                if( D[v] + g[v][i].Y >= L ) {
                    roads.insert( MP( min(v,g[v][i].X),max(v,g[v][i].X) ) );
                }
                D[ g[v][i].X ] = D[v] + g[v][i].Y;
                q.push( g[v][i].X );
            }
        }
    }
    cout << roads.size()<< endl;
    */

    s--;
    vector<i64> d (n, INF),  p(n);
    d[s] = 0;
    set < pair<int,i64> > q;
    q.insert (make_pair (d[s], s));
    while (!q.empty()) {
        int v = q.begin()->second;
        q.erase (q.begin());

        for (size_t j=0; j<g[v].size(); ++j) {
            i64 to = g[v][j].first,
                len = g[v][j].second;
            if (d[v] + len < d[to]) {
                q.erase (make_pair (d[to], to));
                d[to] = d[v] + len;
                p[to] = v;
                q.insert (make_pair (d[to], to));
            }
        }
    }

    i64 L;

    cin >> L;
    int ans = 0;
    /*FOR(i,0,n) {
        if( d[i]==L ) {
            ans ++;
        }
    }
    */

    FOR(i,0,m) {
        i64 A = d[vertex[i].X.X], B = d[vertex[i].X.Y];
        if( A > L && B > L )
            continue;
        /*if( A >= L || B >= L ) {
            ans++;
            continue;
        }*/
        A = A + B + vertex[i].Y;
        if( A%2 ) {
            if( A/2 >= L )
                ans += 2;
        }
        else {
            if( A/2==L )
                ans++;
            else
                if( A/2 > L )
                    ans += 2;
        }
    }

    FOR(i,0,n)
        if( d[i]==L )
            ans -= SZ(g[i])-1;

    cout << ans << endl;

    return 0;
}


//#pragma comment(linker,"/STACK:16777216") /*16Mb*/
//#pragma comment(linker,"/STACK:33554432") /*32Mb*/
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<numeric>
#include<sstream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<memory>
#include<string>
#include<vector>
#include<cctype>
#include<list>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;

typedef unsigned long long      ui64;
typedef long long               i64;
typedef vector<int>             VI;
typedef vector<bool>            VB;
typedef vector<VI>              VVI;
typedef vector<string>          VS;
typedef pair<int,int>           PII;
typedef map<string,int>         MSI;
typedef set<int>                SI;
typedef set<string>             SS;
typedef map<int,int>            MII;
typedef pair<double,double>     PDD;

#define PB                      push_back
#define MP                      make_pair
#define X                       first
#define Y                       second
#define FOR(i, a, b)            for(int i = (a); i < (b); ++i)
#define RFOR(i, a, b)           for(int i = (a) - 1; i >= (b); --i)
#define CLEAR(a, b)             memset(a, b, sizeof(a))
#define SZ(a)                   int((a).size())
#define ALL(a)                  (a).begin(), (a).end()
#define RALL(a)                 (a).rbegin(), (a).rend()

const i64 INF = 1000*1000*1000*100010;

int main()
{
    int n,m,s;
    cin >> n >> m >> s;
    vector< vector< pair<int,i64> > > g(n);
    vector< pair<PII,i64> > vertex(m);
    FOR(i,0,m) {
        int a, b, c;
        scanf("%d%d%d",&a,&b,&c);
        a--;b--;
        g[a].PB( MP(b,c) );
        g[b].PB( MP(a,c) );
        vertex[i] = MP(MP(a,b),c);
    }
    /*
    int L;
    cin >> L;

    queue<int> q;
    q.push(s);
    vector<i64> D(n,INF);
    D[s] = 0;
    set<PII> roads;
    while(!q.empty()) {
        int v = q.front();
        q.pop();
        int len = D[v];
        FOR(i,0,SZ(g[v])) {
            if( D[v] + g[v][i].Y <= D[ g[v][i].X ] ) {
                if( D[v] + g[v][i].Y >= L ) {
                    roads.insert( MP( min(v,g[v][i].X),max(v,g[v][i].X) ) );
                }
                D[ g[v][i].X ] = D[v] + g[v][i].Y;
                q.push( g[v][i].X );
            }
        }
    }
    cout << roads.size()<< endl;
    */

    s--;
    vector<i64> d (n, INF),  p(n);
    d[s] = 0;
    set < pair<i64,int> > q;
    q.insert (make_pair (d[s], s));
    while (!q.empty()) {
        int v = q.begin()->second;
        q.erase (q.begin());

        for (size_t j=0; j<g[v].size(); ++j) {
            i64 to = g[v][j].first,
                len = g[v][j].second;
            if (d[v] + len < d[to]) {
                q.erase (make_pair (d[to], to));
                d[to] = d[v] + len;
                p[to] = v;
                q.insert (make_pair (d[to], to));
            }
        }
    }

    i64 L;

    cin >> L;
    int ans = 0;
    /*FOR(i,0,n) {
        if( d[i]==L ) {
            ans ++;
        }
    }
    */

    FOR(i,0,m) {
        i64 A = d[vertex[i].X.X], B = d[vertex[i].X.Y];
        if( A > L && B > L )
            continue;
        /*if( A >= L || B >= L ) {
            ans++;
            continue;
        }*/
        A = A + B + vertex[i].Y;
        if( A%2 ) {
            if( A/2 >= L )
                ans += 2;
        }
        else {
            if( A/2==L )
                ans++;
            else
                if( A/2 > L )
                    ans += 2;
        }
    }

    FOR(i,0,n)
        if( d[i]==L )
            ans -= SZ(g[i])-1;

    cout << ans << endl;

    return 0;
}


//#pragma comment(linker,"/STACK:16777216") /*16Mb*/
//#pragma comment(linker,"/STACK:33554432") /*32Mb*/
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<numeric>
#include<sstream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<memory>
#include<string>
#include<vector>
#include<cctype>
#include<list>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;

typedef unsigned long long      ui64;
typedef long long               i64;
typedef vector<int>             VI;
typedef vector<bool>            VB;
typedef vector<VI>              VVI;
typedef vector<string>          VS;
typedef pair<int,int>           PII;
typedef map<string,int>         MSI;
typedef set<int>                SI;
typedef set<string>             SS;
typedef map<int,int>            MII;
typedef pair<double,double>     PDD;

#define PB                      push_back
#define MP                      make_pair
#define X                       first
#define Y                       second
#define FOR(i, a, b)            for(int i = (a); i < (b); ++i)
#define RFOR(i, a, b)           for(int i = (a) - 1; i >= (b); --i)
#define CLEAR(a, b)             memset(a, b, sizeof(a))
#define SZ(a)                   int((a).size())
#define ALL(a)                  (a).begin(), (a).end()
#define RALL(a)                 (a).rbegin(), (a).rend()

int main()
{
    long long INF = 100000LL * 100000LL * 100LL;

    int n,m,s;
    cin >> n >> m >> s;
    vector< vector< pair<int,i64> > > g(n);
    vector< pair<PII,i64> > vertex(m);
    FOR(i,0,m) {
        int a, b, c;
        scanf("%d%d%d",&a,&b,&c);
        a--;b--;
        g[a].PB( MP(b,c) );
        g[b].PB( MP(a,c) );
        vertex[i] = MP(MP(a,b),c);
    }
    /*
    int L;
    cin >> L;

    queue<int> q;
    q.push(s);
    vector<i64> D(n,INF);
    D[s] = 0;
    set<PII> roads;
    while(!q.empty()) {
        int v = q.front();
        q.pop();
        int len = D[v];
        FOR(i,0,SZ(g[v])) {
            if( D[v] + g[v][i].Y <= D[ g[v][i].X ] ) {
                if( D[v] + g[v][i].Y >= L ) {
                    roads.insert( MP( min(v,g[v][i].X),max(v,g[v][i].X) ) );
                }
                D[ g[v][i].X ] = D[v] + g[v][i].Y;
                q.push( g[v][i].X );
            }
        }
    }
    cout << roads.size()<< endl;
    */

    s--;
    vector<i64> d (n, INF),  p(n);
    d[s] = 0;
    set < pair<i64,int> > q;
    q.insert (make_pair (d[s], s));
    while (!q.empty()) {
        int v = q.begin()->second;
        q.erase (q.begin());

        for (size_t j=0; j<g[v].size(); ++j) {
            i64 to = g[v][j].first,
                len = g[v][j].second;
            if (d[v] + len < d[to]) {
                q.erase (make_pair (d[to], to));
                d[to] = d[v] + len;
                p[to] = v;
                q.insert (make_pair (d[to], to));
            }
        }
    }

    i64 L;

    cin >> L;
    int ans = 0;
    /*FOR(i,0,n) {
        if( d[i]==L ) {
            ans ++;
        }
    }
    */

    FOR(i,0,m) {
        i64 A = d[vertex[i].X.X], B = d[vertex[i].X.Y];
        if( A > L && B > L )
            continue;

        if( A==L && B==L ) {
            continue;
        }

        if( A == L ) {
            //ans++;
            if( B + vertex[i].Y > L && B<L )
                ans++;
            continue;
        }

        if( B == L ) {
            //ans++;
            if( A + vertex[i].Y > L && A<L )
                ans++;
            continue;
        }

        i64 C = A + B + vertex[i].Y;

        if( A > L && B < L ) {
            if( B + vertex[i].Y  > L )
                ans++;
            continue;
        }

        if( A < L && B > L ) {
            if( A + vertex[i].Y  > L )
                ans++;
            continue;
        }

        if( C%2 ) {
            if( C/2 >= L )
                ans += 2;
        }
        else {
            if( C/2==L )
                ans++;
            else
                if( C/2 > L )
                    ans += 2;
        }
    }

    FOR(i,0,n)
        if( d[i]==L )
            ans++;
            //ans -= SZ(g[i])-1;

    cout << ans << endl;

    return 0;
}


//#pragma comment(linker,"/STACK:16777216") /*16Mb*/
//#pragma comment(linker,"/STACK:33554432") /*32Mb*/
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<numeric>
#include<sstream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<memory>
#include<string>
#include<vector>
#include<cctype>
#include<list>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;

typedef unsigned long long      ui64;
typedef long long               i64;
typedef vector<int>             VI;
typedef vector<bool>            VB;
typedef vector<VI>              VVI;
typedef vector<string>          VS;
typedef pair<int,int>           PII;
typedef map<string,int>         MSI;
typedef set<int>                SI;
typedef set<string>             SS;
typedef map<int,int>            MII;
typedef pair<double,double>     PDD;

#define PB                      push_back
#define MP                      make_pair
#define X                       first
#define Y                       second
#define FOR(i, a, b)            for(int i = (a); i < (b); ++i)
#define RFOR(i, a, b)           for(int i = (a) - 1; i >= (b); --i)
#define CLEAR(a, b)             memset(a, b, sizeof(a))
#define SZ(a)                   int((a).size())
#define ALL(a)                  (a).begin(), (a).end()
#define RALL(a)                 (a).rbegin(), (a).rend()

const i64 INF = 1000*1000*1000*100010;

int main()
{
    int n,m,s;
    cin >> n >> m >> s;
    vector< vector< pair<int,i64> > > g(n);
    vector< pair<PII,i64> > vertex(m);
    FOR(i,0,m) {
        int a, b, c;
        scanf("%d%d%d",&a,&b,&c);
        a--;b--;
        g[a].PB( MP(b,c) );
        g[b].PB( MP(a,c) );
        vertex[i] = MP(MP(a,b),c);
    }
    /*
    int L;
    cin >> L;

    queue<int> q;
    q.push(s);
    vector<i64> D(n,INF);
    D[s] = 0;
    set<PII> roads;
    while(!q.empty()) {
        int v = q.front();
        q.pop();
        int len = D[v];
        FOR(i,0,SZ(g[v])) {
            if( D[v] + g[v][i].Y <= D[ g[v][i].X ] ) {
                if( D[v] + g[v][i].Y >= L ) {
                    roads.insert( MP( min(v,g[v][i].X),max(v,g[v][i].X) ) );
                }
                D[ g[v][i].X ] = D[v] + g[v][i].Y;
                q.push( g[v][i].X );
            }
        }
    }
    cout << roads.size()<< endl;
    */

    s--;
    vector<i64> d (n, INF),  p(n);
    d[s] = 0;
    set < pair<i64,int> > q;
    q.insert (make_pair (d[s], s));
    while (!q.empty()) {
        int v = q.begin()->second;
        q.erase (q.begin());

        for (size_t j=0; j<g[v].size(); ++j) {
            i64 to = g[v][j].first,
                len = g[v][j].second;
            if (d[v] + len < d[to]) {
                q.erase (make_pair (d[to], to));
                d[to] = d[v] + len;
                p[to] = v;
                q.insert (make_pair (d[to], to));
            }
        }
    }

    i64 L;

    cin >> L;
    int ans = 0;
    /*FOR(i,0,n) {
        if( d[i]==L ) {
            ans ++;
        }
    }
    */

    FOR(i,0,m) {
        i64 A = d[vertex[i].X.X], B = d[vertex[i].X.Y];
        if( A > L && B > L )
            continue;
        /*if( A >= L || B >= L ) {
            ans++;
            continue;
        }*/
        if( A == L || B== L ) {
            ans += 2;
            continue;
        }
        A = A + B + vertex[i].Y;
        if( A%2 ) {
            if( A/2 >= L )
                ans += 2;
        }
        else {
            if( A/2==L )
                ans++;
            else
                if( A/2 > L )
                    ans += 2;
        }
    }

    FOR(i,0,n)
        if( d[i]==L )
            ans -= SZ(g[i])-1;

    cout << ans << endl;

    return 0;
}


//#pragma comment(linker,"/STACK:16777216") /*16Mb*/
//#pragma comment(linker,"/STACK:33554432") /*32Mb*/
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<numeric>
#include<sstream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<memory>
#include<string>
#include<vector>
#include<cctype>
#include<list>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;

typedef unsigned long long      ui64;
typedef long long               i64;
typedef vector<int>             VI;
typedef vector<bool>            VB;
typedef vector<VI>              VVI;
typedef vector<string>          VS;
typedef pair<int,int>           PII;
typedef map<string,int>         MSI;
typedef set<int>                SI;
typedef set<string>             SS;
typedef map<int,int>            MII;
typedef pair<double,double>     PDD;

#define PB                      push_back
#define MP                      make_pair
#define X                       first
#define Y                       second
#define FOR(i, a, b)            for(int i = (a); i < (b); ++i)
#define RFOR(i, a, b)           for(int i = (a) - 1; i >= (b); --i)
#define CLEAR(a, b)             memset(a, b, sizeof(a))
#define SZ(a)                   int((a).size())
#define ALL(a)                  (a).begin(), (a).end()
#define RALL(a)                 (a).rbegin(), (a).rend()

const i64 INF = 1000*1000*1000*100010;

int main()
{
    int n,m,s;
    cin >> n >> m >> s;
    vector< vector< pair<int,i64> > > g(n);
    vector< pair<PII,i64> > vertex(m);
    FOR(i,0,m) {
        int a, b, c;
        scanf("%d%d%d",&a,&b,&c);
        a--;b--;
        g[a].PB( MP(b,c) );
        g[b].PB( MP(a,c) );
        vertex[i] = MP(MP(a,b),c);
    }
    /*
    int L;
    cin >> L;

    queue<int> q;
    q.push(s);
    vector<i64> D(n,INF);
    D[s] = 0;
    set<PII> roads;
    while(!q.empty()) {
        int v = q.front();
        q.pop();
        int len = D[v];
        FOR(i,0,SZ(g[v])) {
            if( D[v] + g[v][i].Y <= D[ g[v][i].X ] ) {
                if( D[v] + g[v][i].Y >= L ) {
                    roads.insert( MP( min(v,g[v][i].X),max(v,g[v][i].X) ) );
                }
                D[ g[v][i].X ] = D[v] + g[v][i].Y;
                q.push( g[v][i].X );
            }
        }
    }
    cout << roads.size()<< endl;
    */

    s--;
    vector<i64> d (n, INF),  p(n);
    d[s] = 0;
    set < pair<i64,int> > q;
    q.insert (make_pair (d[s], s));
    while (!q.empty()) {
        int v = q.begin()->second;
        q.erase (q.begin());

        for (size_t j=0; j<g[v].size(); ++j) {
            i64 to = g[v][j].first,
                len = g[v][j].second;
            if (d[v] + len < d[to]) {
                q.erase (make_pair (d[to], to));
                d[to] = d[v] + len;
                p[to] = v;
                q.insert (make_pair (d[to], to));
            }
        }
    }

    i64 L;

    cin >> L;
    int ans = 0;
    /*FOR(i,0,n) {
        if( d[i]==L ) {
            ans ++;
        }
    }
    */

    FOR(i,0,m) {
        i64 A = d[vertex[i].X.X], B = d[vertex[i].X.Y];
        if( A > L && B > L )
            continue;
        /*if( A >= L || B >= L ) {
            ans++;
            continue;
        }*/
        if( A==L && B==L ) {
            ans+=2;
            continue;
        }

        if( A == L ) {
            ans++;
            if( B + vertex[i].Y > L )
                ans++;
            continue;
        }

        if( B == L ) {
            ans++;
            if( A + vertex[i].Y > L )
                ans++;
            continue;
        }

        A = A + B + vertex[i].Y;
        if( A%2 ) {
            if( A/2 >= L )
                ans += 2;
        }
        else {
            if( A/2==L )
                ans++;
            else
                if( A/2 > L )
                    ans += 2;
        }
    }

    FOR(i,0,n)
        if( d[i]==L )
            ans -= SZ(g[i])-1;

    cout << ans << endl;

    return 0;
}


#include <cstdio>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <memory.h>
#include <set>

using namespace std;

const int maxN = 100011;

struct TNode {
    int id, value;

    TNode(int _id, int _value){
        id = _id;
        value = _value;
    }
};

class cmp {
public:
    bool operator () (TNode &a, TNode &b){
        return a.value > b.value;
    }
};

int n, m;
vector <int> edges[maxN], weight[maxN], edges_id[maxN];
bool mark[maxN], flag[maxN];
int d[maxN];
int tot, L;

bool visited[maxN][1111];

const int INF = 999999999;

void Dijkstra(int u){
    memset(mark, false, sizeof(mark));
    memset(visited, false, sizeof(visited));

    for (int i = 0; i <= n; i++) d[i] = INF;
    d[u] = 0;

    TNode x = TNode(u, 0);
    priority_queue <TNode, vector <TNode>, cmp> pq;
    pq.push(x);

    while (!pq.empty()){
        while (!pq.empty() && mark[ pq.top().id ]) pq.pop();
        if (!pq.empty()){
            TNode x = pq.top();
            pq.pop();
            u = x.id;
            int value = x.value;
            mark[u] = true;

            for (int i = 0; i < edges[u].size(); i++){
                int v = edges[u][i];
                int w = weight[u][i];
                int e_id = edges_id[u][i];

                if (mark[v]) continue;

                int tmp = value + w;

                if (tmp < d[v]){
                    d[v] = tmp;
                    pq.push(TNode(v, tmp));
                }
            }
        }
    }
}

int main(){
    int s;
    scanf("%d%d%d", &n, &m, &s);

    for (int i = 0; i < m; i++){
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        edges[a].push_back(b);
        edges[b].push_back(a);

        weight[a].push_back(w);
        weight[b].push_back(w);

        edges_id[a].push_back(i);
        edges_id[b].push_back(i);
    }

    scanf("%d", &L);

    if (L == 0){
        printf("1\n");
        return 0;
    }

    tot = 0;
    Dijkstra(s);

    for (int i = 1; i <= n; i++){
        if (d[i] == L) tot++;
        for (int j = 0; j < edges[i].size(); j++){
            int u = i, v = edges[i][j];
            int w = weight[i][j];
            int id = edges_id[i][j];

            if (d[u] < L && d[u] + w > L){
                int x = d[u] + w - L;
                if (d[v] + x >= L){
                    int p = L - d[u];
                    if (v > u) p = x;

                    if (!visited[id][p]){
                        visited[id][p] = true;
                        tot++;
                    }
                }
            }
        }
    }

    printf("%d\n", tot);

//  system("pause");
    return 0;
}


#include <cstdio>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <memory.h>
#include <set>

using namespace std;

const int maxN = 100011;

struct TNode {
    int id, value;

    TNode(int _id, int _value){
        id = _id;
        value = _value;
    }
};

class cmp {
public:
    bool operator () (TNode &a, TNode &b){
        return a.value < b.value;
    }
};

int n, m;
vector <int> edges[maxN], weight[maxN], edges_id[maxN];
bool mark[maxN], flag[maxN];
int d[maxN];
int tot, L;

bool visited[maxN][1111];

const int INF = 999999999;

void Dijkstra(int u){
    memset(mark, false, sizeof(mark));
    memset(visited, false, sizeof(visited));

    for (int i = 0; i <= n; i++) d[i] = INF;
    d[u] = 0;

    TNode x = TNode(u, 0);
    priority_queue <TNode, vector <TNode>, cmp> pq;
    pq.push(x);

    while (!pq.empty()){
        while (!pq.empty() && mark[ pq.top().id ]) pq.pop();
        if (!pq.empty()){
            TNode x = pq.top();
            pq.pop();
            u = x.id;
            int value = x.value;
            mark[u] = true;

            for (int i = 0; i < edges[u].size(); i++){
                int v = edges[u][i];
                int w = weight[u][i];
                int e_id = edges_id[u][i];

                if (mark[v]) continue;

                int tmp = value + w;

                if (tmp == L){
                    if (!flag[v]){
                        flag[v] = true;
                        tot++;
                    }
                }
                else if (tmp > L && value < L){
                    int p = tmp - L;
                    if (v > u) p = w - p;

                    if (!visited[e_id][p]){
                        visited[e_id][p] = true;
                        tot++;
                    }
                }

                if (tmp < d[v]){
                    d[v] = tmp;
                    pq.push(TNode(v, tmp));
                }
            }
        }
    }
}

int main(){
    int s;
    scanf("%d%d%d", &n, &m, &s);

    for (int i = 0; i < m; i++){
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        edges[a].push_back(b);
        edges[b].push_back(a);

        weight[a].push_back(w);
        weight[b].push_back(w);

        edges_id[a].push_back(i);
        edges_id[b].push_back(i);
    }

    scanf("%d", &L);

    if (L == 0){
        printf("1\n");
        return 0;
    }

    tot = 0;
    Dijkstra(s);

    for (int i = 0; i < n; i++){
        for (int j = 0; j < edges[i].size(); j++){
            int u = i, v = edges[i][j];
            int w = weight[i][j];
            int id = edges_id[i][j];

            if (d[u] < L && d[u] + w > L){
                int x = d[u] + w - L;
                if (d[v] + x > L){
                    int p = L - d[u];
                    if (v > u) p = x;

                    if (!visited[id][p]){
                        visited[id][p] = true;
                        tot++;
                    }
                }
            }
        }
    }

    printf("%d\n", tot);

//  system("pause");
    return 0;
}


#include <cstdio>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <memory.h>
#include <set>

using namespace std;

const int maxN = 100011;

struct TNode {
    int id, value;

    TNode(int _id, int _value){
        id = _id;
        value = _value;
    }
};

class cmp {
public:
    bool operator () (TNode &a, TNode &b){
        return a.value < b.value;
    }
};

int n, m;
vector <int> edges[maxN], weight[maxN], edges_id[maxN];
bool mark[maxN], flag[maxN];
int d[maxN];
int tot, L;

bool visited[maxN][1111];

const int INF = 999999999;

void Dijkstra(int u){
    memset(mark, false, sizeof(mark));
    memset(visited, false, sizeof(visited));

    for (int i = 0; i <= n; i++) d[i] = INF;
    d[u] = 0;

    TNode x = TNode(u, 0);
    priority_queue <TNode, vector <TNode>, cmp> pq;
    pq.push(x);

    while (!pq.empty()){
        while (!pq.empty() && mark[ pq.top().id ]) pq.pop();
        if (!pq.empty()){
            TNode x = pq.top();
            pq.pop();
            u = x.id;
            int value = x.value;
            mark[u] = true;

            for (int i = 0; i < edges[u].size(); i++){
                int v = edges[u][i];
                int w = weight[u][i];
                int e_id = edges_id[u][i];

                if (mark[v]) continue;

                int tmp = value + w;

                if (tmp == L){
                    if (!flag[v]){
                        flag[v] = true;
                        tot++;
                    }
                }
                else if (tmp > L && value < L){
                    int p = tmp - L;
                    if (v > u) p = w - p;

                    if (!visited[e_id][p]){
                        visited[e_id][p] = true;
                        tot++;
                    }
                }

                if (tmp < d[v]){
                    d[v] = tmp;
                    pq.push(TNode(v, tmp));
                }
            }
        }
    }
}

int main(){
    int s;
    scanf("%d%d%d", &n, &m, &s);

    for (int i = 0; i < m; i++){
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        edges[a].push_back(b);
        edges[b].push_back(a);

        weight[a].push_back(w);
        weight[b].push_back(w);

        edges_id[a].push_back(i);
        edges_id[b].push_back(i);
    }

    scanf("%d", &L);

    tot = 0;
    Dijkstra(s);

    for (int i = 0; i < n; i++){
        for (int j = 0; j < edges[i].size(); j++){
            int u = i, v = edges[i][j];
            int w = weight[i][j];
            int id = edges_id[i][j];

            if (d[u] < L && d[u] + w > L){
                int x = d[u] + w - L;
                if (d[v] + x > L){
                    int p = L - d[u];
                    if (v > u) p = x;

                    if (!visited[id][p]){
                        visited[id][p] = true;
                        tot++;
                    }
                }
            }
        }
    }

    printf("%d\n", tot);

//  system("pause");
    return 0;
}


#include<stdio.h>
#include<queue>
#include<vector>
#include<string.h>
using namespace std;

#define maxm 100100
#define inf 1<<30
#define ii __int64

struct node{
    int no;
    ii cost;
};

bool operator<(const node &a,const node &b){
    return a.cost>b.cost;
}

struct edge{
    int u,v;
    ii  cost;
};

bool flag[maxm];
edge edges[maxm];
vector<node>v[maxm];
priority_queue<node>pq;
ii d[maxm];
ii len;
int s,n;

void dij(int s);

int main(){

    int i,j,k,l,test,t=1,c,m,q;
    node temp,temp1;

//  freopen("in.txt","r",stdin);
    //scanf("%d",&test);

    scanf("%d %d %d",&n,&m,&s);

    for(i=1;i<=m;i++){
        scanf("%d %d %d",&k,&l,&c);
        edges[i].u=k; edges[i].v=l; edges[i].cost=c;
        temp.cost=c; temp.no=l;
        v[k].push_back(temp);
        temp.no=k;
        v[l].push_back(temp);
    }

    scanf("%I64d",&len);

    dij(s);

    ii ans=0;

    for(i=1;i<=n;i++){
        if(d[i]==len) ans++;
    }

    ii a,b,d1,e;
    int fl;

    for(i=1;i<=m;i++){
        k=edges[i].u; l=edges[i].v;
        c=0;
        fl=0;
        if(d[k]<len){
            if(d[k]+edges[i].cost>len){
                a=len-d[k];
                d1=edges[i].cost-a;
                if(d[k]+a<d[l]+d1){
                    ans++;
                    c++;
                }
                else if(d[k]+a==d[l]+d1){
                        ans++;
                        continue;

                }
            //  c++;
            }
        }
        if(d[l]<len){
            if(d[l]+edges[i].cost>len){
                b=len-d[l];
                e=edges[i].cost-b;
                if(d[l]+b<d[k]+e){
                    ans++;
                    c++;
                }
            }
        }

    //  if(c==2){
    //      if(a+b>=edges[i].cost) ans--;
    //  }
    }

    printf("%I64d\n",ans);

    return 0;
}

void dij(int s){

    int i,j,k,l;
    node temp,temp1;

    memset(flag,0,sizeof(flag));

    while(!pq.empty()) pq.pop();

    temp.cost=0;temp.no=s;
    d[s]=0; flag[s]=1;
    pq.push(temp);

    while(!pq.empty()){

        temp=pq.top(); pq.pop();

        i=temp.no;

        for(j=0;j<v[i].size();j++){
            temp1=v[i][j];
            k=temp1.no;
            if(flag[k]==0){
                d[k]=d[i]+temp1.cost;
                temp1.no=k; temp1.cost=d[k];
                pq.push(temp1);
                flag[k]=1;
                continue;
            }
            if(d[k]>d[i]+temp1.cost){
                d[k]=d[i]+temp1.cost;
                temp1.no=k; temp1.cost=d[k];
                pq.push(temp1);
                flag[k]=1;
                continue;
            }

        }

    }

}


#include<stdio.h>
#include<queue>
#include<vector>
#include<string.h>
using namespace std;

#define maxm 100100
#define inf 1<<30
#define ii __int64

struct node{
    int no;
    ii cost;
};

bool operator<(const node &a,const node &b){
    return a.cost>b.cost;
}

struct edge{
    int u,v;
    ii  cost;
};

bool flag[maxm];
edge edges[maxm];
vector<node>v[maxm];
priority_queue<node>pq;
ii d[maxm];
ii len;
int s,n;

void dij(int s);

int main(){

    int i,j,k,l,test,t=1,c,m,q;
    node temp,temp1;

    //freopen("in.txt","r",stdin);
    //scanf("%d",&test);

    scanf("%d %d %d",&n,&m,&s);

    for(i=1;i<=m;i++){
        scanf("%d %d %d",&k,&l,&c);
        edges[i].u=k; edges[i].v=l; edges[i].cost=c;
        temp.cost=c; temp.no=l;
        v[k].push_back(temp);
        temp.no=k;
        v[l].push_back(temp);
    }

    scanf("%I64d",&len);

    dij(s);

    ii ans=0;

    for(i=1;i<=n;i++){
        if(d[i]==len) ans++;
    }

    ii a,b;

    for(i=1;i<=m;i++){
        k=edges[i].u; l=edges[i].v;
        c=0;
        if(d[k]<len){
            if(d[k]+edges[i].cost>len){
                ans++;
                a=len-d[k];
                c++;
            }
        }
        if(d[l]<len){
            if(d[l]+edges[i].cost>len){
                ans++;
                b=len-d[l];
                c++;
            }
        }

        if(c==2){
            if(a+b==edges[i].cost) ans--;
        }
    }

    printf("%I64d\n",ans);

    return 0;
}

void dij(int s){

    int i,j,k,l;
    node temp,temp1;

    memset(flag,0,sizeof(flag));

    while(!pq.empty()) pq.pop();

    temp.cost=0;temp.no=s;
    d[s]=0; flag[s]=1;
    pq.push(temp);

    while(!pq.empty()){

        temp=pq.top(); pq.pop();

        i=temp.no;

        for(j=0;j<v[i].size();j++){
            temp1=v[i][j];
            k=temp1.no;
            if(flag[k]==0){
                d[k]=d[i]+temp1.cost;
                temp1.no=k; temp1.cost=d[k];
                pq.push(temp1);
                flag[k]=1;
                continue;
            }
            if(d[k]>d[i]+temp1.cost){
                d[k]=d[i]+temp1.cost;
                temp1.no=k; temp1.cost=d[k];
                pq.push(temp1);
                flag[k]=1;
                continue;
            }

        }

    }

}


#include<stdio.h>
#include<queue>
#include<vector>
#include<string.h>
using namespace std;

#define maxm 100100
#define inf 1<<30
#define ii __int64

struct node{
    int no;
    ii cost;
};

bool operator<(const node &a,const node &b){
    return a.cost>b.cost;
}

struct edge{
    int u,v;
    ii  cost;
};

bool flag[maxm];
edge edges[maxm];
vector<node>v[maxm];
priority_queue<node>pq;
ii d[maxm];
ii len;
int s,n;

void dij(int s);

int main(){

    int i,j,k,l,test,t=1,c,m,q;
    node temp,temp1;

    //freopen("in.txt","r",stdin);
    //scanf("%d",&test);

    scanf("%d %d %d",&n,&m,&s);

    for(i=1;i<=m;i++){
        scanf("%d %d %d",&k,&l,&c);
        edges[i].u=k; edges[i].v=l; edges[i].cost=c;
        temp.cost=c; temp.no=l;
        v[k].push_back(temp);
        temp.no=k;
        v[l].push_back(temp);
    }

    scanf("%I64d",&len);

    dij(s);

    ii ans=0;

    for(i=1;i<=n;i++){
        if(d[i]==len) ans++;
    }

    ii a,b;

    for(i=1;i<=m;i++){
        k=edges[i].u; l=edges[i].v;
        c=0;
        if(d[k]<len){
            if(d[k]+edges[i].cost>len){
                ans++;
                a=len-d[k];
                c++;
            }
        }
        if(d[l]<len){
            if(d[l]+edges[i].cost>len){
                ans++;
                b=len-d[l];
                c++;
            }
        }

        if(c==2){
            if(a+b>=edges[i].cost) ans--;
        }
    }

    printf("%I64d\n",ans);

    return 0;
}

void dij(int s){

    int i,j,k,l;
    node temp,temp1;

    memset(flag,0,sizeof(flag));

    while(!pq.empty()) pq.pop();

    temp.cost=0;temp.no=s;
    d[s]=0; flag[s]=1;
    pq.push(temp);

    while(!pq.empty()){

        temp=pq.top(); pq.pop();

        i=temp.no;

        for(j=0;j<v[i].size();j++){
            temp1=v[i][j];
            k=temp1.no;
            if(flag[k]==0){
                d[k]=d[i]+temp1.cost;
                temp1.no=k; temp1.cost=d[k];
                pq.push(temp1);
                flag[k]=1;
                continue;
            }
            if(d[k]>d[i]+temp1.cost){
                d[k]=d[i]+temp1.cost;
                temp1.no=k; temp1.cost=d[k];
                pq.push(temp1);
                flag[k]=1;
                continue;
            }

        }

    }

}


#pragma comment(linker, "/stack:64000000")

#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <algorithm>
#include <queue>

using namespace std;

#define REP(i, n) for (int (i) = 0; (i) < (n); (i)++)
#define all(v) (v).begin(), (v).end()
#define sz(v) (int)(v).size()

const int INF = 1000000000 + 10;

int main() {
#ifndef ONLINE_JUDGE
	freopen("test.in", "r", stdin);
	freopen("test.out", "w", stdout);
#endif
	int n, m, s;
	cin >> n >> m >> s;
	--s;
	vector < vector < pair<int,int> > > g (n);
	REP(i, m) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		--a, --b;
		g[a].push_back(make_pair(b, c));
		g[b].push_back(make_pair(a, c));
	}
	vector<int> d (n, INF),  p (n,-1);
	d[s] = 0;
	priority_queue < pair<int,int> > q;
	q.push (make_pair (0, s));
	while (!q.empty()) {
		int v = q.top().second,  cur_d = -q.top().first;
		q.pop();
		if (cur_d > d[v])  continue;

		for (size_t j=0; j<g[v].size(); ++j) {
			int to = g[v][j].first,
				len = g[v][j].second;
			if (d[v] + len < d[to]) {
				d[to] = d[v] + len;
				p[to] = v;
				q.push (make_pair (-d[to], to));
			}
		}
	}
	//REP(i, n) cout << d[i] << " ";
	//cout << endl;
	int len;
	cin >> len;
	if (len == 0) {
		cout << 1;
		return 0;
	}
	int res = 0;
	REP(i, n) {
		if (len == d[i]) {
			++res;
		}
	}
	int add = 0;
	REP(i, n) {
		REP(j, sz(g[i])) {
			int a = i, b = g[i][j].first, c = g[i][j].second;
			int x = -1, y = -1;
			if (d[a] < len && d[a] + c > len && c - (len - d[a]) + d[b] >= len) {
				x = len - d[a];
				++add;
			}
			if (d[b] < len && d[b] + c > len && c - (len - d[b]) + d[a] >= len) {
				y = len - d[b];
				++add;
			}
			if (x != -1 && y != -1 && x + y == c) {
				--add;
			}
		}
	}
	cout << res + add / 2;
	return 0;
}


#pragma comment(linker, "/stack:64000000")

#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <algorithm>
#include <queue>

using namespace std;

#define REP(i, n) for (int (i) = 0; (i) < (n); (i)++)
#define all(v) (v).begin(), (v).end()
#define sz(v) (int)(v).size()

const int INF = 1000000000 + 10;

int main() {
#ifndef ONLINE_JUDGE
	freopen("test.in", "r", stdin);
	freopen("test.out", "w", stdout);
#endif
	int n, m, s;
	cin >> n >> m >> s;
	--s;
	vector < vector < pair<int,int> > > g (n);
	REP(i, m) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		--a, --b;
		g[a].push_back(make_pair(b, c));
		g[b].push_back(make_pair(a, c));
	}
	vector<int> d (n, INF),  p (n,-1);
	d[s] = 0;
	priority_queue < pair<int,int> > q;
	q.push (make_pair (0, s));
	while (!q.empty()) {
		int v = q.top().second,  cur_d = -q.top().first;
		q.pop();
		if (cur_d > d[v])  continue;

		for (size_t j=0; j<g[v].size(); ++j) {
			int to = g[v][j].first,
				len = g[v][j].second;
			if (d[v] + len < d[to]) {
				d[to] = d[v] + len;
				p[to] = v;
				q.push (make_pair (-d[to], to));
			}
		}
	}
	//REP(i, n) cout << d[i] << " ";
	//cout << endl;
	int len;
	cin >> len;
	if (len == 0) {
		cout << 1;
		return 0;
	}
	int res = 0;
	REP(i, n) {
		if (len == d[i]) {
			++res;
		}
	}
	map <pair <int, int>, set <int> > h;
	REP(i, n) {
		REP(j, sz(g[i])) {
			int to = g[i][j].first;
			int dst = g[i][j].second;
			if (to != p[i] && d[i] < len && d[i] + dst > len) {
				pair <int, int> p(min(i, to), max(i, to));
				int t;
				if (min(i, to) == i) t = len - d[i];
				else t = d[i] + dst - len;
				if (!(h.count(p) && h[p].count(t))) {
					h[p].insert(t);
					++res;
				}
			}
		}
	}
	cout << res;
	return 0;
}


#pragma comment(linker, "/stack:64000000")

#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <algorithm>
#include <queue>

using namespace std;

#define REP(i, n) for (int (i) = 0; (i) < (n); (i)++)
#define all(v) (v).begin(), (v).end()
#define sz(v) (int)(v).size()

const int INF = 1000000000 + 10;

int main() {
#ifndef ONLINE_JUDGE
	freopen("test.in", "r", stdin);
	freopen("test.out", "w", stdout);
#endif
	int n, m, s;
	cin >> n >> m >> s;
	--s;
	vector < vector < pair<int,int> > > g (n);
	REP(i, m) {
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		--a, --b;
		g[a].push_back(make_pair(b, c));
		g[b].push_back(make_pair(a, c));
	}
	vector<int> d (n, INF),  p (n,-1);
	d[s] = 0;
	priority_queue < pair<int,int> > q;
	q.push (make_pair (0, s));
	while (!q.empty()) {
		int v = q.top().second,  cur_d = -q.top().first;
		q.pop();
		if (cur_d > d[v])  continue;

		for (size_t j=0; j<g[v].size(); ++j) {
			int to = g[v][j].first,
				len = g[v][j].second;
			if (d[v] + len < d[to]) {
				d[to] = d[v] + len;
				p[to] = v;
				q.push (make_pair (-d[to], to));
			}
		}
	}
	//REP(i, n) cout << d[i] << " ";
	//cout << endl;
	int len;
	cin >> len;
	if (len == 0) {
		cout << 1;
		return 0;
	}
	int res = 0;
	REP(i, n) {
		if (len == d[i]) {
			++res;
		}
	}
	int add = 0;
	REP(i, n) {
		REP(j, sz(g[i])) {
			int a = i, b = g[i][j].first, c = g[i][j].second;
			int x = -1, y = -1;
			if (d[a] < len && p[a] != b && d[a] + c > len) {
				x = len - d[a];
				++add;
			}
			if (d[b] < len && p[b] != a && d[b] + c > len) {
				y = len - d[b];
				++add;
			}
			if (x != -1 && y != -1 && x + y == c) {
				--add;
			}
		}
	}
	cout << res + add / 2;
	return 0;
}


#include <iostream>
#include <sstream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <string>
#include <ctime>
#include <cmath>
using namespace std;

const int N = 100005;
const int INF = 1e9;

typedef pair<int, int> pii;
typedef pair<pii, int> piii;
#define X first
#define Y second

int n, m, s, l;
vector<pii> g[N];
int d[N];

struct cmpSet
{
    bool operator()(int a, int b) const
    {
        return d[a] < d[b] || d[a] == d[b] && a < b;
    }
};

struct cmpSetUsed
{
    bool operator()(piii a, piii b) const
    {
        return a.X < b.X || a.X == b.X && a.Y < b.Y;
    }
};

set<int, cmpSet> q;
set<piii, cmpSetUsed> used;

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

    scanf("%d%d%d", &n, &m, &s);
    s--;
    for (int i = 0; i < m; i++)
    {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        u--; v--;
        g[u].push_back(pii(v, w));
        g[v].push_back(pii(u, w));
    }
    scanf("%d", &l);

    fill(d, d + n, INF);
    d[s] = 0;
    q.insert(s);
    while (!q.empty())
    {
        int v = *q.begin();
        q.erase(q.begin());
        for (int i = 0; i < (int)g[v].size(); i++)
        {
            int to = g[v][i].X;
            int w = g[v][i].Y;
            if (d[to] > d[v] + w)
            {
                q.erase(to);
                d[to] = d[v] + w;
                q.insert(to);
            }
        }
    }

    int cnt = 0;
    for (int i = 0; i < n; i++)
    {
        if (d[i] == l)
            ++cnt;
        for (int j = 0; j < (int)g[i].size(); j++)
            if (d[i] < l && d[i] + g[i][j].Y > l && used.find(piii(pii(i, g[i][j].X), l - d[i])) == used.end())
            {
                ++cnt;
                used.insert(piii(pii(i, g[i][j].X), l - d[i]));
                used.insert(piii(pii(g[i][j].X, i), d[i] + g[i][j].Y - l));
            }
    }

    printf("%d", cnt);

    return 0;
}


#include <iostream>
#include <sstream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <string>
#include <ctime>
#include <cmath>
using namespace std;

const int N = 100005;
const int INF = 1e9;

typedef pair<int, int> pii;
#define X first
#define Y second

int n, m, s, l;
vector<pii> g[N];
int d[N];

struct cmpSet
{
    bool operator()(int a, int b) const
    {
        return d[a] < d[b] || d[a] == d[b] && a < b;
    }
};

set<int, cmpSet> q;

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

    scanf("%d%d%d", &n, &m, &s);
    s--;
    for (int i = 0; i < m; i++)
    {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        u--; v--;
        g[u].push_back(pii(v, w));
        g[v].push_back(pii(u, w));
    }
    scanf("%d", &l);

    fill(d, d + n, INF);
    d[s] = 0;
    q.insert(s);
    while (!q.empty())
    {
        int v = *q.begin();
        q.erase(q.begin());
        for (int i = 0; i < (int)g[v].size(); i++)
        {
            int to = g[v][i].X;
            int w = g[v][i].Y;
            if (d[to] > d[v] + w)
            {
                q.erase(to);
                d[to] = d[v] + w;
                q.insert(to);
            }
        }
    }

    int cnt = 0;
    for (int i = 0; i < n; i++)
    {
        if (d[i] == l)
            cnt += 2;
        for (int j = 0; j < (int)g[i].size(); j++)
            if (d[i] < l && d[i] + g[i][j].Y > l)
            {
                if (l - d[i] == d[i] + g[i][j].Y - l)
                    ++cnt;
                else
                    cnt += 2;
            }
    }

    printf("%d", cnt / 2);

    return 0;
}


#include <iostream>
#include <sstream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <string>
#include <ctime>
#include <cmath>
using namespace std;

const int N = 100005;
const int INF = 1e9;

typedef pair<int, int> pii;
#define X first
#define Y second

int n, m, s, l;
vector<pii> g[N];
int d[N];

struct cmpSet
{
    bool operator()(int a, int b) const
    {
        return d[a] < d[b] || d[a] == d[b] && a < b;
    }
};

set<int, cmpSet> q;

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

    scanf("%d%d%d", &n, &m, &s);
    s--;
    for (int i = 0; i < m; i++)
    {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        u--; v--;
        g[u].push_back(pii(v, w));
        g[v].push_back(pii(u, w));
    }
    scanf("%d", &l);

    fill(d, d + n, INF);
    d[s] = 0;
    q.insert(s);
    while (!q.empty())
    {
        int v = *q.begin();
        q.erase(q.begin());
        for (int i = 0; i < (int)g[v].size(); i++)
        {
            int to = g[v][i].X;
            int w = g[v][i].Y;
            if (d[to] > d[v] + w)
            {
                q.erase(to);
                d[to] = d[v] + w;
                q.insert(to);
            }
        }
    }

    int cnt = 0;
    for (int i = 0; i < n; i++)
    {
        if (d[i] == l)
            cnt += 2;
        for (int j = 0; j < (int)g[i].size(); j++)
            if (d[i] < l && d[i] + g[i][j].Y > l)
            {
                if (l == d[g[i][j].X] + g[i][j].Y - (l - d[i]))
                    ++cnt;
                else if (l < d[g[i][j].X] + g[i][j].Y - (l - d[i]))
                    cnt += 2;
            }
    }

    printf("%d", cnt / 2);

    return 0;
}