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 <bits/stdc++.h>
using namespace std;
const long long INF = 10000000000000000;
const int maxN = 1000 + 10;
const int maxM = 20000 + 10;
long long d1;
bool er[maxM];
vector<int> paths1;
struct Edge {
  int from, to;
  long long dist;
};
struct HeapNode {
  long long d;
  int u;
  bool operator<(const HeapNode& rhs) const { return d > rhs.d; }
};
vector<Edge> edges;
vector<int> G[maxN];
bool done[maxN];
long long d[maxN];
int p[maxM];
int id[maxM];
struct Dijkstra {
  int n, m;
  void init(int n) {
    this->n = n;
    for (int i = 0; i < n; i++) G[i].clear();
    edges.clear();
  }
  void AddEdge(int from, int to, long long dist, int ff) {
    edges.push_back((Edge){from, to, dist});
    m = edges.size();
    G[from].push_back(m - 1);
    id[m - 1] = ff;
  }
  void dijkstra(int s) {
    priority_queue<HeapNode> Q;
    for (int i = 0; i < n; i++) d[i] = INF;
    d[s] = 0;
    memset(done, 0, sizeof(done));
    Q.push((HeapNode){0, s});
    while (!Q.empty()) {
      HeapNode x = Q.top();
      Q.pop();
      int u = x.u;
      if (done[u]) continue;
      done[u] = true;
      for (int i = 0; i < G[u].size(); i++) {
        Edge& e = edges[G[u][i]];
        if (d[e.to] > d[u] + e.dist) {
          d[e.to] = d[u] + e.dist;
          p[e.to] = G[u][i];
          Q.push((HeapNode){d[e.to], e.to});
        }
      }
    }
  }
  void GetShortestPaths(int s, int u) {
    dijkstra(s);
    if (d[u] >= INF) {
      d1 = d[u];
      return;
    }
    for (int i = u; i <= u; i++) {
      d1 = d[i];
      paths1.clear();
      int t = i;
      paths1.push_back(t);
      while (t != s) {
        paths1.push_back(edges[p[t]].from);
        t = edges[p[t]].from;
      }
      reverse(paths1.begin(), paths1.end());
    }
  }
};
Dijkstra solver;
Edge ei[10000 + 10];
int main() {
  int n, m, s, t;
  long long L;
  while (~scanf("%d%d%lld%d%d", &n, &m, &L, &s, &t)) {
    memset(er, 0, sizeof(er));
    for (long long i = 0; i < m; i++) {
      scanf("%d%d%lld", &ei[i].from, &ei[i].to, &ei[i].dist);
      if (ei[i].dist == 0) er[i] = 1;
    }
    solver.init(n);
    for (int i = 0; i < m; i++) {
      if (er[i]) ei[i].dist = L;
      solver.AddEdge(ei[i].from, ei[i].to, ei[i].dist, 0);
      solver.AddEdge(ei[i].to, ei[i].from, ei[i].dist, 0);
    }
    solver.GetShortestPaths(s, t);
    if (d1 < L)
      printf("NO\n");
    else if (d1 == L) {
      printf("YES\n");
      for (long long i = 0; i < m; i++)
        printf("%d %d %lld\n", ei[i].from, ei[i].to, ei[i].dist);
    } else {
      solver.init(n);
      for (int i = 0; i < m; i++) {
        if (er[i]) {
          ei[i].dist = 1;
          solver.AddEdge(ei[i].from, ei[i].to, ei[i].dist, i + 1);
          solver.AddEdge(ei[i].to, ei[i].from, ei[i].dist, i + 1);
        } else {
          solver.AddEdge(ei[i].from, ei[i].to, ei[i].dist, 0);
          solver.AddEdge(ei[i].to, ei[i].from, ei[i].dist, 0);
        }
      }
      solver.GetShortestPaths(s, t);
      if (d1 > L)
        printf("NO\n");
      else if (d1 == L) {
        printf("YES\n");
        for (int i = 0; i < m; i++)
          printf("%d %d %lld\n", ei[i].from, ei[i].to, ei[i].dist);
      } else {
        for (;;) {
          long long add = L - d1;
          for (int i = 0; i < paths1.size(); i++) {
            int u = paths1[i];
            bool ok = false;
            for (int j = 0; j < G[u].size(); j++) {
              int ee = G[u][j];
              if (id[ee] && edges[G[u][j]].to == paths1[i + 1]) {
                edges[ee].dist += add;
                ei[id[ee] - 1].dist = edges[ee].dist;
                ok = true;
                break;
              }
            }
            if (ok) break;
          }
          solver.GetShortestPaths(s, t);
          if (d1 < L) continue;
          printf("YES\n");
          for (int i = 0; i < m; i++) {
            printf("%d %d %lld\n", ei[i].from, ei[i].to, ei[i].dist);
          }
          break;
        }
      }
    }
  }
  return 0;
}
