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

//Be Name Khoda
//no comment...
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T> using ordered_multiset =  tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;
typedef long long ll;
typedef long double ld;
const int MOD = (int)1e9 + 7;
const int MAXN = (int)1e4 + 7;
const ll inf = (ll)1e18;
const int infint = (int)1e9;
ll we[MAXN], good[MAXN], dist[MAXN], sar1[MAXN], sar2[MAXN], n, m, need, dist2[MAXN];
vector<ll> G[MAXN];
void dijkstra(ll root)
{
	for (int i = 1; i <= n; i++)
		dist[i] = inf;
	dist[root] = 0;
	set<pair<ll, ll> > S;
	for (int i = 0; i < n; i++)
		S.insert({dist[i], i});
	for (int i = 1; i <= n; i++)
	{
		pair<ll, ll> P = *S.begin();
		S.erase(P);
		for (auto u : G[P.second])
		{
			int t = sar1[u];
			if(t == P.second)
				t = sar2[u];
			if(dist[P.second] + we[u] < dist[t])
			{
				S.erase({dist[t], t});
				dist[t] = min(dist[t], dist[P.second] + we[u]);
				S.insert({dist[t], t});
			}
		}
	}
}
void dijkstra2(int root)
{
	for (int i = 1; i <= n; i++)
		dist2[i] = inf;
	dist2[root] = 0;
	set<pair<ll, ll> > S;
	for (int i = 0; i < n; i++)
		S.insert({dist2[i], i});
	for (int i = 1; i <= n; i++)
	{
		pair<ll, ll> P = *S.begin();
		S.erase(P);
		for (auto u : G[P.second])
		{
			int t = sar1[u];
			if(t == P.second)
				t = sar2[u];
				
			if(good[u] && dist2[P.second] + we[u] < need + dist[t])
				we[u] = need + dist[t] - dist2[P.second];
				
			if(dist2[P.second] + we[u] < dist2[t])
			{
				S.erase({dist2[t], t});
				dist2[t] = min(dist2[t], dist2[P.second] + we[u]);
				S.insert({dist2[t], t});
			}
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	int L, s, t;
	cin >> n >> m >> L >> s >> t;
	for (int i = 0; i < m; i++)
	{
		ll u, v, w;
		cin >> u >> v >> w;
		G[u].push_back(i);
		G[v].push_back(i);
		sar1[i] = u, sar2[i] = v;
		we[i] = w;
		if(w == 0)
		{
			we[i] = 1;
			good[i] = 1;
		}
	}
	dijkstra(s);
	if(dist[t] > L)
		return cout << "NO", 0;
	need = L - dist[t];
	dijkstra2(s);
	if(dist2[t] == L)
	{
		cout << "YES\n";
		for (int i = 0; i < m; i++)
			cout << sar1[i] << " " << sar2[i] << " " << we[i] << "\n";
	}
	else
		cout << "NO";
}
