7 9 999999999 0 3
0 1 0
1 2 0
2 3 0
0 4 1
4 1 1
1 5 499999999
5 2 499999999
2 6 1
6 3 1
 7 9 320 0 3
0 1 0
1 2 0
2 3 0
0 4 1
4 1 1
1 5 100
5 2 100
2 6 59
6 3 61
 4 5 7 0 3
0 1 0
1 2 3
2 3 0
0 2 5
1 3 5
 8 9 10 1 0
1 2 1
2 4 1
1 3 0
3 4 0
4 5 0
5 6 1
6 0 1
5 7 0
7 0 0
 4 4 14 1 3
1 3 13
2 3 0
2 0 0
1 0 12
 5 6 1000000000 0 4
0 1 1
2 0 2
3 0 3
4 1 0
4 2 0
3 4 0
 4 5 10 1 2
0 1 3
1 2 0
1 3 4
2 3 4
2 0 6
 4 4 2 1 3
1 3 13
2 3 0
2 0 0
1 0 0
 5 5 2 0 2
0 1 1
1 2 1
0 4 0
4 3 0
3 2 0
 5 5 3 0 2
0 1 1
1 2 1
0 4 0
4 3 0
3 2 0
 4 4 8 1 3
1 3 13
2 3 0
2 0 0
1 0 6
 1000 1 1000000000 998 0
0 999 0
 5 5 1 0 2
0 1 1
1 2 1
0 4 0
4 3 0
3 2 0
 100 1 123456 99 0
0 99 123456
 4 4 13 1 3
1 3 13
2 3 0
2 0 0
1 0 12
 7 9 319 0 3
0 1 0
1 2 0
2 3 0
0 4 1
4 1 1
1 5 100
5 2 100
2 6 59
6 3 61
 1000 1 5 999 0
0 999 0

YES
0 1 1
1 2 999999996
2 3 999999997
0 4 1
4 1 1
1 5 499999999
5 2 499999999
2 6 1
6 3 1
 YES
0 1 1
1 2 199
2 3 318
0 4 1
4 1 1
1 5 100
5 2 100
2 6 59
6 3 61
 YES
0 1 3
1 2 3
2 3 2
0 2 5
1 3 5
 YES
1 2 1
2 4 1
1 3 1
3 4 1
4 5 6
5 6 1
6 0 1
5 7 1
7 0 1
 NO YES
0 1 1
2 0 2
3 0 3
4 1 999999999
4 2 999999998
3 4 999999997
 NO NO YES
0 1 1
1 2 1
0 4 1
4 3 1
3 2 1
 NO YES
1 3 13
2 3 1
2 0 1
1 0 6
 NO NO YES
0 99 123456
 YES
1 3 13
2 3 1
2 0 1
1 0 12
 YES
0 1 1
1 2 198
2 3 317
0 4 1
4 1 1
1 5 100
5 2 100
2 6 59
6 3 61
 YES
0 999 5

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

using namespace std;


#define pii pair<int, int>
#define mp make_pair<int, int>

typedef long long ll;

const int N = 1005;
const int M = 10005;
const ll LINF = 1e18;
const ll INF = 1e10;

struct Edge
{
	Edge(){}
	Edge(int vv, int index) : v(vv), idx(index)
	{
		
	}
	int v;
	int idx;
};


vector<Edge> graph[N];
int s, t;
ll dist[N];

ll we[M];
bool erased[M];
vector<int> nonAssignedEdges;

void dijkstra()
{
	fill(dist, dist + N, LINF);
	set<pair<ll, int> > S;
	set<pair<ll, int> >::iterator iter;
	S.insert(make_pair<ll, int>(0, s));
	dist[s] = 0;
	
	int u, v, idx, i;
	ll w;
	while (!S.empty())
	{
		u = S.begin()->second;
		S.erase(S.begin());
		
		for (i = 0; i < graph[u].size(); i++)
		{
			v = graph[u][i].v;
			idx = graph[u][i].idx;
			w = we[idx];
			if (dist[u] + w < dist[v])
			{
				iter = S.find(make_pair<ll, int>(dist[v], v));
				if (iter != S.end())
				{
					S.erase(iter);
				}
				dist[v] = dist[u] + w;
				S.insert(make_pair<ll, int>(dist[v], v));
			}
		}
	}
}

int main()
{
	int n, m, i, j, u, v, w, idx, num, p;
	ll minDist, maxDist, L;
	scanf("%d%d%lld%d%d", &n, &m, &L, &s, &t);
	for (i = 0; i < m; i++)
	{
		scanf("%d%d%d", &u, &v, &w);
		if (w == 0)
		{
			erased[i] = true;
		}
		graph[u].push_back(Edge(v, i));
		graph[v].push_back(Edge(u, i));
		we[i] = w;
	}
	
	// max
	for (i = 0; i < m; i++)
	{
		if (erased[i])
		{
			we[i] = INF;
		}
	}
	dijkstra();
	maxDist = dist[t];
	
	// min
	for (i = 0; i < m; i++)
	{
		if (erased[i])
		{
			we[i] = 1;
		}
	}
	dijkstra();
	minDist = dist[t];
	
	
	
	if (L < minDist || L > maxDist)
	{
		printf("NO\n");
		return 0;
	}
	
	//list<int> nonAssignedEdges;
	for (i = 0; i < m; i++)
	{
		if (erased[i])
		{
			nonAssignedEdges.push_back(i);
		}
	}
	num = nonAssignedEdges.size();
	
	// use binary search to find minimal p such that nonAssignedEdges[0-p]=1, p+1~num-1=INF and dist[t] <= L
	int d;
	p = num - 1;
	for (d = 1; p - d >= 0; d *= 2);
	
	for (; d; d /= 2)
	{
		if (p - d >= 0)
		{
			for (i = 0; i <= p; i++)
			{
				we[nonAssignedEdges[i]] = 1;
			}
			for (; i < num; i++)
			{
				we[nonAssignedEdges[i]] = INF;
			}
			dijkstra();
			
			if (dist[t] <= L)
			{
				p -= d;
			}
		}
	}
	
	if (num > 0)
	{
		we[nonAssignedEdges[p]] += L - dist[t];
	}
	
	printf("YES\n");
	for (u = 0; u < n; u++)
	{
		for (i = 0; i < graph[u].size(); i++)
		{
			v = graph[u][i].v;
			idx = graph[u][i].idx;
			if (u < v)
			{
				printf("%d %d %lld\n", u, v, we[idx]);
			}
		}
	}
	
	printf("\n");
	return 0;
}