#include<bits/stdc++.h>
#define LL long long
inline LL read(){
	char c=getchar();while (c!='-'&&(c<'0'||c>'9'))c=getchar();
	LL k=0,kk=1;if (c=='-')kk=-1,c=getchar();
	while (c>='0'&&c<='9')k=k*10+c-'0',c=getchar();return k*kk;
}void write(LL x){if (x<0)x=-x,putchar('-');if (x/10)write(x/10);putchar(x%10+'0');}
void writeln(LL x){write(x);puts("");}
using namespace std;
char s[2000010],ss[2000010];
int qaq[2000010],qwq[2000010],f[2000010],ff[2000010];
int n,m,k,d,ddd;
inline void add(int x[],int y[],int z[],int xx,int yy,int zz){//将y和z合并为x,n
	if (yy==0){for (int i=0;i<zz+xx-1;i++)x[i]=z[i];return;}
	yy+=xx-1;zz+=xx-1;xx=yy+zz-xx+1;int ll=xx-zz;//起始位置
	for (int i=0;i<xx;i++)qaq[i]=i<yy?y[i]:i;
	for (int i=ll;i<xx;i++)qwq[i-ll]=qaq[i];
	for (int i=ll;i<xx;i++)qaq[i]=qwq[z[i-ll]];
	for (int i=0;i<xx;i++)x[i]=qaq[i];
}
signed main(){
	scanf("%s",s);n=strlen(s);m=read();
	for (int l=1;l<=m;l++){
		k=read();d=read();ddd=0;
		for (int i=0;i<d;i++)
			for (int j=i;j<k;j+=d)ff[ddd++]=j;
		int nn=n-k+1,i=0,kk=0;
		while (nn){
			if (nn&1)add(f,f,ff,k,kk,1<<i),kk+=1<<i;
			i++;nn>>=1;if (nn)add(ff,ff,ff,k,1<<(i-1),1<<(i-1));
		}for (int i=0;i<n;i++)ss[i]=s[i];
		for (int i=0;i<n;i++)s[i]=ss[f[i]];
		for (int i=0;i<n;i++)putchar(s[i]);puts("");
	}
}


#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
char s[1000100];int n,m;char ans[1000100];
int tmp[1000100],to[1000100],T[1000100];
int To[1000100];int k[1000100],d[1000100];
namespace bf
{
	inline void Add()
{
	for(int i=0;i<n;i++) tmp[i]=to[To[i]];
	for(int i=0;i<n;i++) to[i]=tmp[i];
}
inline void Sort(int l,int r,int d)
{
	int len=r-l+1;
	for(int i=0,cur=l;i<len;i++,cur++) tmp[i]=to[cur];
	int tot=0;
	for(int i=0;i<d;i++) for(int j=i;j<len;j+=d) T[tot++]=tmp[j];
	for(int i=0,cur=l;i<len;i++,cur++) to[cur]=T[i];
}
inline void print()
{
	for(int i=0;i<n;i++) ans[i]=s[to[i]];
	ans[n]='\0';
	puts(ans);
}
inline void bf()
{
	for(int i=1;i<=m;i++)
	{
		int l=0,r=k[i]-1;
		while(r<n)
		{
			Sort(l,r,d[i]);
			l++;r++;
		}
		print();
	}
}
int main()
{
	for(int i=0;i<n;i++) to[i]=i;
	for(int i=1;i<=m;i++) scanf("%d%d",k+i,d+i);
	bf();
	return 0;
}
}
inline void Add()
{
	for(int i=0;i<n;i++) tmp[i]=to[To[i]];
	for(int i=0;i<n;i++) To[i]=tmp[i];
}
inline void Sort(int l,int r,int d)
{
	int len=r-l+1;
	for(register int i=0,cur=l;i<len;i++,cur++) tmp[i]=to[cur];
	int tot=0;
	for(register int i=0;i<d;i++) for(register int j=i;j<len;j+=d) to[j]=tmp[tot++];
}
inline void print()
{
	for(register int i=0;i<n;i++) ans[To[i]]=s[i];
	ans[n]='\0';puts(ans);
}
bool vis[1000100];int loop[1000100],tot;
inline void change(int k,int d)
{
	for(int i=0;i<n;i++) to[i]=i;
	Sort(0,k-1,d);
	for(int i=0;i<n;i++)
	{
		to[i]--;
		if(to[i]==-1) to[i]=n-1;
	}
	register int times=n-k+1;memset(vis,0,sizeof(vis));
	for(register int i=0;i<n;i++) if(!vis[i])
	{
		vis[i]=1;loop[tot=1]=i;int cur=to[i];
		while(!vis[cur]) vis[cur]=1,loop[++tot]=cur,cur=to[cur];
		for(register int j=1;j<=tot;j++) tmp[loop[j]]=loop[(j+times%tot-1)%tot+1];
	}
	for(int i=0;i<n;i++) to[i]=tmp[i];
	for(int i=0;i<n;i++) (to[i]+=times)%=n;
	Add();
}
int main()
{
	scanf("%s",s);n=strlen(s);
	scanf("%d",&m);if(m>=10000) return bf::main();
	for(register int i=0;i<n;i++) To[i]=i;
	for(register int i=1;i<=m;i++)
	{
		int k,b;scanf("%d%d",&k,&b);
		change(k,b);
		print();
	}
	return 0;
}
/*
qwerty
3
4 2
6 3
5 2
*/


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

typedef vector <int> per;

vector <int> getI(int n) {
	vector <int> a;
	for (int i = 0; i < n; i++) {
		a.push_back(i);
	}
	return a;
}

per operator * (const per &a, const per &b) {
	per res(a.size());
	for (int i = 0; i < a.size(); i++) {
		res[i] = b[a[i]];
	}
	return res;
}

per get_inv(const per &a) {
	per b(a.size());
	for (int i = 0; i < a.size(); i++) {
		b[a[i]] = i;
	}
	return b;
}

char s[1000010];

int main () {
	scanf("%s", s);
	int n = strlen(s);
	per P = getI(n);
	int q; scanf("%d", &q);
	while (q--) {
		int k, d; scanf("%d%d", &k, &d);
		per trans;
		for (int i = 0; i < n; i++) {
			int x = i < k ? i % d * (k / d) + min(i % d, k % d) + i / d : i;
			trans.push_back(x ? x - 1 : n - 1);
		}
		int T = n - k + 1;
		while (T) {
			if (T & 1) P = P * trans;
			trans = trans * trans, T >>= 1;
		}
		trans.clear();
		for (int i = 0; i < n; i++) {
			trans.push_back((i - k + 1 + n + n) % n);
		}
		P = P * trans;
		per Q = get_inv(P);
		for (int i = 0; i < n; i++) {
			printf("%c", s[Q[i]]);
		}
		printf("\n");
	}
	return 0;
}


#include <cassert>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <vector>
#include <cmath>
using namespace std;

#define all(a) a.begin(), a.end()
#define rep(i, a, b) for(int i=int(a); i<=int(b); ++i)
#define irep(i, a, b) for(int i=int(a); i>=int(b); --i)
#define repn(i, n) rep(i, 0, (n)-1)
#define irepn(i, n) irep(i, (n)-1, 0)
#define fillchar(a, x) memset(a, x, sizeof(a))
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#ifdef DEBUG
    #define _debug(args...) { fprintf(stderr, args); fflush(stderr); }
#else
    #define _debug(args...) {}
#endif
typedef long long LL;
typedef pair<LL,LL> PLL;
typedef pair<int,int> PII;
typedef pair<double,double> PDD;
typedef vector<LL> VL;
typedef vector<int> VI;
typedef vector<PII> VPI;
typedef vector<string> VS;
template<class T> bool setmax(T &_a, T _b) { if(_b>_a) { _a=_b; return true; } return false; }
template<class T> bool setmin(T &_a, T _b) { if(_b<_a) { _a=_b; return true; } return false; }
template<class T> T gcd(T _a, T _b) { return _b==0?_a:gcd(_b,_a%_b); }

const int MAXN=1000010;
const int MAXLog=20;

char s[MAXN], tmp[MAXN];
int n, m;

int lnk[MAXN], go[MAXN][MAXLog];
int a[MAXN], b[MAXN];

void solve(int k, int d0) {
    int cur=0;
    repn(j, d0) for(int i=j; i<k; i+=d0) a[cur++]=i;
    assert(cur==k);

    repn(i, k) lnk[i]=a[i]+1; lnk[k]=k;
    repn(i, k+1) go[i][0]=lnk[i];
    rep(j, 1, MAXLog-1) repn(i, k+1) go[i][j]=go[go[i][j-1]][j-1];

    repn(i, n) {
        int init=max(0, i-n+k), init_pos=i-init;
        int steps=min(i, n-k)+1;
        int d=0, x=init;
        irepn(j, MAXLog)
            if(go[x][j]!=k && (d+(1<<j))<=steps) {
                d+=(1<<j); x=go[x][j];
            }
        if(x!=k && (d+1)<=steps) {
            ++d; x=go[x][0];
        }
        int pos=init_pos-d;
        b[i]=pos+x;
        //printf("i=%d init=%d init_pos=%d steps=%d d=%d x=%d pos=%d\n",i,init,init_pos,steps,d,x,pos);
    }
    //repn(i, n) printf("%d ", b[i]); printf("\n");
    repn(i, n) tmp[i]=s[b[i]];
    memcpy(s, tmp, sizeof(s));
}

int main() {
    scanf("%s", s); n=(int)strlen(s);
    scanf("%d", &m);
    while(m--) {
        int k, d; scanf("%d%d", &k,&d);
        solve(k, d);
        s[n]='\0'; printf("%s\n", s);
    }
    return 0;
}


#include <cassert>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <vector>
#include <cmath>
using namespace std;

#define all(a) a.begin(), a.end()
#define rep(i, a, b) for(int i=int(a); i<=int(b); ++i)
#define irep(i, a, b) for(int i=int(a); i>=int(b); --i)
#define repn(i, n) rep(i, 0, (n)-1)
#define irepn(i, n) irep(i, (n)-1, 0)
#define fillchar(a, x) memset(a, x, sizeof(a))
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#ifdef DEBUG
    #define _debug(args...) { fprintf(stderr, args); fflush(stderr); }
#else
    #define _debug(args...) {}
#endif
typedef long long LL;
typedef pair<LL,LL> PLL;
typedef pair<int,int> PII;
typedef pair<double,double> PDD;
typedef vector<LL> VL;
typedef vector<int> VI;
typedef vector<PII> VPI;
typedef vector<string> VS;
template<class T> bool setmax(T &_a, T _b) { if(_b>_a) { _a=_b; return true; } return false; }
template<class T> bool setmin(T &_a, T _b) { if(_b<_a) { _a=_b; return true; } return false; }
template<class T> T gcd(T _a, T _b) { return _b==0?_a:gcd(_b,_a%_b); }

const int MAXN=1000010;
const int MAXLog=20;

char s[MAXN], tmp[MAXN];
int n, m;

int lnk[MAXN], go[MAXN][MAXLog];
int a[MAXN], b[MAXN];

void solve(int k, int d0) {
    int cur=0;
    repn(j, d0) for(int i=j; i<k; i+=d0) a[cur++]=i;
    assert(cur==k);

    int maxlog=0; while((1<<maxlog)<=n) ++maxlog;

    repn(i, k) lnk[i]=a[i]+1; lnk[k]=k;
    repn(i, k+1) go[i][0]=lnk[i];
    rep(j, 1, maxlog-1) repn(i, k+1) go[i][j]=go[go[i][j-1]][j-1];

    repn(i, n) {
        int init=max(0, i-n+k), init_pos=i-init;
        int steps=min(i, n-k)+1, rest=steps;
        int x=init;
        irepn(j, maxlog)
            if(rest>=(1<<j)) {
                int y=go[x][j];
                if(y!=k) {
                    x=y; rest-=(1<<j);
                }
            }
        if(x!=k && rest>0) {
            --rest; x=go[x][0];
        }
        int pos=init_pos-(steps-rest);
        b[i]=pos+x;
        //printf("i=%d init=%d init_pos=%d steps=%d d=%d x=%d pos=%d\n",i,init,init_pos,steps,d,x,pos);
    }
    //repn(i, n) printf("%d ", b[i]); printf("\n");
    repn(i, n) tmp[i]=s[b[i]];
    memcpy(s, tmp, sizeof(s));
}

int main() {
    gets(s); n=(int)strlen(s);
    scanf("%d", &m);
    while(m--) {
        int k, d; scanf("%d%d", &k,&d);
        solve(k, d);
        s[n]='\0'; puts(s); //printf("%s\n", s);
    }
    return 0;
}


#include <cassert>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <vector>
#include <cmath>
using namespace std;

#define all(a) a.begin(), a.end()
#define rep(i, a, b) for(int i=int(a); i<=int(b); ++i)
#define irep(i, a, b) for(int i=int(a); i>=int(b); --i)
#define repn(i, n) rep(i, 0, (n)-1)
#define irepn(i, n) irep(i, (n)-1, 0)
#define fillchar(a, x) memset(a, x, sizeof(a))
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#ifdef DEBUG
    #define _debug(args...) { fprintf(stderr, args); fflush(stderr); }
#else
    #define _debug(args...) {}
#endif
typedef long long LL;
typedef pair<LL,LL> PLL;
typedef pair<int,int> PII;
typedef pair<double,double> PDD;
typedef vector<LL> VL;
typedef vector<int> VI;
typedef vector<PII> VPI;
typedef vector<string> VS;
template<class T> bool setmax(T &_a, T _b) { if(_b>_a) { _a=_b; return true; } return false; }
template<class T> bool setmin(T &_a, T _b) { if(_b<_a) { _a=_b; return true; } return false; }
template<class T> T gcd(T _a, T _b) { return _b==0?_a:gcd(_b,_a%_b); }

const int MAXN=1000010;
const int MAXLog=20;

char s[MAXN], tmp[MAXN];
int n, m;

int lnk[MAXN], go[MAXN][MAXLog];
int a[MAXN], b[MAXN];

void solve(int k, int d0) {
    int cur=0;
    repn(j, d0) for(int i=j; i<k; i+=d0) a[cur++]=i;
    assert(cur==k);

    int maxlog=0; while((1<<(maxlog+1))<=n) ++maxlog;

    repn(i, k) lnk[i]=a[i]+1; lnk[k]=k;
    repn(i, k+1) go[i][0]=lnk[i];
    rep(j, 1, maxlog-1) repn(i, k+1) go[i][j]=go[go[i][j-1]][j-1];

    repn(i, n) {
        int init=max(0, i-n+k), init_pos=i-init;
        int steps=min(i, n-k)+1, rest=steps;
        int x=init;
        irepn(j, maxlog)
            if(rest>=(1<<j)) {
                int y=go[x][j];
                if(y!=k) {
                    x=y; rest-=(1<<j);
                }
            }
        if(x!=k && rest>0) {
            --rest; x=go[x][0];
        }
        int pos=init_pos-(steps-rest);
        b[i]=pos+x;
        //printf("i=%d init=%d init_pos=%d steps=%d d=%d x=%d pos=%d\n",i,init,init_pos,steps,d,x,pos);
    }
    //repn(i, n) printf("%d ", b[i]); printf("\n");
    repn(i, n) tmp[i]=s[b[i]];
    memcpy(s, tmp, sizeof(s));
}

int main() {
    gets(s); n=(int)strlen(s);
    scanf("%d", &m);
    while(m--) {
        int k, d; scanf("%d%d", &k,&d);
        solve(k, d);
        s[n]='\0'; puts(s); //printf("%s\n", s);
    }
    return 0;
}


#include <cassert>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <vector>
#include <cmath>
using namespace std;

#define all(a) a.begin(), a.end()
#define rep(i, a, b) for(int i=int(a); i<=int(b); ++i)
#define irep(i, a, b) for(int i=int(a); i>=int(b); --i)
#define repn(i, n) rep(i, 0, (n)-1)
#define irepn(i, n) irep(i, (n)-1, 0)
#define fillchar(a, x) memset(a, x, sizeof(a))
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#ifdef DEBUG
    #define _debug(args...) { fprintf(stderr, args); fflush(stderr); }
#else
    #define _debug(args...) {}
#endif
typedef long long LL;
typedef pair<LL,LL> PLL;
typedef pair<int,int> PII;
typedef pair<double,double> PDD;
typedef vector<LL> VL;
typedef vector<int> VI;
typedef vector<PII> VPI;
typedef vector<string> VS;
template<class T> bool setmax(T &_a, T _b) { if(_b>_a) { _a=_b; return true; } return false; }
template<class T> bool setmin(T &_a, T _b) { if(_b<_a) { _a=_b; return true; } return false; }
template<class T> T gcd(T _a, T _b) { return _b==0?_a:gcd(_b,_a%_b); }

const int MAXN=1000010;
const int MAXLog=20;

char s[MAXN], tmp[MAXN];
int n, m;

int lnk[MAXN], go[MAXN][MAXLog];
int a[MAXN], b[MAXN];

void solve(int k, int d0) {
    int cur=0;
    repn(j, d0) for(int i=j; i<k; i+=d0) a[cur++]=i;
    assert(cur==k);

    int maxlog=0; while((1<<maxlog)<=n) ++maxlog;

    repn(i, k) lnk[i]=a[i]+1; lnk[k]=k;
    repn(i, k+1) go[i][0]=lnk[i];
    rep(j, 1, maxlog-1) repn(i, k+1) go[i][j]=go[go[i][j-1]][j-1];

    repn(i, n) {
        int init=max(0, i-n+k), init_pos=i-init;
        int steps=min(i, n-k)+1, rest=steps;
        int x=init;
        irepn(j, maxlog)
            if(rest>=(1<<j)) {
                int y=go[x][j];
                if(y!=k) {
                    x=y; rest-=(1<<j);
                }
            }
        if(x!=k && rest>0) {
            --rest; x=go[x][0];
        }
        int pos=init_pos-(steps-rest);
        b[i]=pos+x;
        //printf("i=%d init=%d init_pos=%d steps=%d d=%d x=%d pos=%d\n",i,init,init_pos,steps,d,x,pos);
    }
    //repn(i, n) printf("%d ", b[i]); printf("\n");
    repn(i, n) tmp[i]=s[b[i]];
    repn(i, n) s[i]=tmp[i];
}

int main() {
    //*
    gets(s); n=(int)strlen(s);
    scanf("%d", &m);
    while(m--) {
        int k, d; scanf("%d%d", &k,&d);
        solve(k, d);
        s[n]='\0'; puts(s); //printf("%s\n", s);
    }
    /*/
    s[0]='a', s[1]='\0', n=1;
    repn(i, 1000000) {
        solve(1,1);
        }
    //*/
    return 0;
}


#include<bits/stdc++.h>
#define LL long long
inline LL read(){
	char c=getchar();while (c!='-'&&(c<'0'||c>'9'))c=getchar();
	LL k=0,kk=1;if (c=='-')kk=-1,c=getchar();
	while (c>='0'&&c<='9')k=k*10+c-'0',c=getchar();return k*kk;
}void write(LL x){if (x<0)x=-x,putchar('-');if (x/10)write(x/10);putchar(x%10+'0');}
void writeln(LL x){write(x);puts("");}
using namespace std;
char s[2000010],ss[2000010];
int qaq[2000010],qwq[2000010],f[2000010],ff[2000010];
int n,m,k,d,ddd;
inline void add(int x[],int y[],int z[],int xx,int yy,int zz){//将y和z合并为x,n
	if (yy==0){for (int i=0;i<zz+xx-1;i++)x[i]=z[i];return;}
	yy+=xx-1;zz+=xx-1;xx=yy+zz-xx+1;int ll=xx-zz;//起始位置
	for (int i=0;i<xx;i++)qaq[i]=i<yy?y[i]:i;
	for (int i=ll;i<xx;i++)qwq[i-ll]=qaq[i];
	for (int i=ll;i<xx;i++)qaq[i]=qwq[z[i-ll]];
	for (int i=0;i<xx;i++)x[i]=qaq[i];
}
signed main(){
	scanf("%s",s);n=strlen(s);m=read();
	for (int l=1;l<=m;l++){//m
		k=read();d=read();ddd=0;
		for (int i=0;i<d;i++)
			for (int j=i;j<k;j+=d)ff[ddd++]=j;
		int nn=n-k+1,i=0,kk=0;
		while (nn){//log
			if (nn&1)add(f,f,ff,k,kk,1<<i),kk+=1<<i;
			i++;nn>>=1;if (nn)add(ff,ff,ff,k,1<<(i-1),1<<(i-1));
		}for (int i=0;i<n;i++)ss[i]=s[i];
		for (int i=0;i<n;i++)s[i]=ss[f[i]];
		for (int i=0;i<n;i++)putchar(s[i]);puts("");
	}
}


#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 1000005;

int n;

inline void cheng(int* a, int* b, int* ans)
{
	for(int i = 1; i <= n; ++i)
		ans[i] = a[b[i]];
}

int TTT[maxn];
inline void pow(int* a, int b, int* ans)
{
	for(int i = 1; i <= n; ++i)
		ans[i] = i;
	for(; b; b >>= 1)
	{
		if(b & 1)
		{
			cheng(a, ans, TTT);
			for(int i = 1; i <= n; ++i)
				ans[i] = TTT[i];
		}
		cheng(a, a, TTT);
		for(int i = 1; i <= n; ++i)
			a[i] = TTT[i];
	}
}

inline void you(int* a, int b, int* ans)
{
	b = (b % n + n) % n;
	for(int i = 1; i <= n; ++i)
		ans[(i + b - 1) % n + 1] = a[i];
}

inline void zuo(int* a, int b, int* ans)
{
	you(a, -b, ans);
}

char C[maxn], s[maxn];

int T[maxn];

inline void zhuan(int* yl, int k)
{
	zuo(yl, 1, T);
	pow(T, n - k + 1, yl);
	you(yl, n - k + 1, T);
	for(int i = 1; i <= n; ++i)
		yl[i] = T[i];
}

int yl[maxn], tmp[maxn];

int main()
{
	gets(C + 1);
	n = strlen(C + 1);
	int m;
	scanf("%d", &m);
	while(m--)
	{
		int k, d;
		scanf("%d%d", &k, &d);
		for(int i = 1; i <= n; ++i)
			yl[i] = i;
		int cnt = 0;
		for(int i = 1; i <= d; ++i)
			for(int j = i; j <= k; j += d)
				tmp[++cnt] = yl[j];
		for(int i = 1; i <= k; ++i)
			yl[i] = tmp[i];
//		cout << "cnt = " << cnt << endl;
//		for(int i = 1; i <= n; ++i)
//			cout << yl[i] << ' ';
//		cout << endl;
		zhuan(yl, k);
		for(int i = 1; i <= n; ++i)
			putchar(s[i] = C[yl[i]]);
		puts("");
		for(int i = 1; i <= n; ++i)
			C[i] = s[i];
//		puts(C + 1);
//		cout << "n = " << n << endl;
	}
	return 0;
}

/*
qwerty
3
4 2
6 3
5 2
*/


#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1000010;

char s[N], ns[N];
int n, m, S[N], L[N], Z[N], LS[N], tmp[N];

void multi() {
	for (int i = 0; i < n; ++i) tmp[i] = LS[LS[i]];
	for (int i = 0; i < n; ++i) LS[i] = tmp[i];
}
int main() {
	scanf("%s", s), n = strlen(s);
	for (int i = 0; i < n; ++i) {
		L[i] = i? i - 1: n - 1;
	}
	for (scanf("%d", &m); m--; ) {
		int k, d;
		scanf("%d %d", &k, &d);

		for (int i = 0; i < n; ++i) S[i] = i;
		int tot = 0;
		for (int x = 0; x < d; ++x)
			for (int y = x; y < k; y += d) {
				S[y] = tot++;
			}
		for (int i = 0; i < n; ++i) Z[i] = S[i];

		for (int i = 0; i < n; ++i) LS[i] = S[L[i]];
		for (int t = n - k; t; t >>= 1, multi())
			if (t & 1) {
				for (int i = 0; i < n; ++i) Z[i] = LS[Z[i]];
			}

		for (int i = 0; i < n; ++i) ns[Z[i]] = s[i];
		for (int i = 0; i < n; ++i) s[(i + (n - k)) % n] = ns[i];
		printf("%s\n", s);
	}
}


//
//  main.cpp
//  Codeforces
//
//  Created by Luke Zhu on 9/25/16.
//  Copyright © 2016 Luke Zhu. All rights reserved.
//

// Problem D
# include <iostream>
# include <array>
# include <vector>
# include <algorithm>
# include <map>

# define MAX_DIST 1000000000000000000

using namespace std;

// Dijkstra O(3.3*10^5) up to 1000 times
// Let adj matrix of erased equal 1
// Get shortest path
// If greater than, print NO
// If less/equal desired, add (desired - length) to erased edges, rerun dijkstra
// Do the above until all erased are filled (NO),
// or until dist = desired (YES)

int nodes, edges, start, target;
long long int desired_len;
array<array<int, 1000>, 1000> unweighted_matrix; // if not -1, equals index on adj list
array<vector<pair<int, long long int>>, 1000> adj_list; // holds to_node and weight
vector<pair<int, int>> edge_list;
array<bool, 1000> visited;
array<long long int, 1000> dist; // from source
array<pair<int, bool>, 1000> parent; // true if an erased node

void dijkstra() {
    // Initialize dijkstra arrays;
    dist.fill(MAX_DIST);
    parent.fill(pair<int, bool>(-1, false)); // parent index, and whether connecting edge is erased
    visited.fill(false);
    dist[start] = 0;

    for (int i = 0; i < nodes; ++i) {
        long long int min_dist = MAX_DIST;
        int closest = -1;
        for (int j = 0; j < nodes; ++j) {
            if (!visited[j] && dist[j] < min_dist) {
                min_dist = dist[j];
                closest = j;
            }
        }
        visited[closest] = true;
        // cout << closest << "\n";

        for (int j = 0; j < adj_list[closest].size(); ++j) {
            int v = adj_list[closest][j].first;
            long long int w = adj_list[closest][j].second;
            if (dist[v] > dist[closest] + w) {
                dist[v] = dist[closest] + w;
                // cout << v << " " << dist[v] << "\n";
                if (unweighted_matrix[closest][v] != -1) {
                    parent[v] = pair<int, bool>(closest, true);
                } else {
                    parent[v] = pair<int, bool>(closest, false);
                }
            }
        }
    }
    // cout << dist[target] << "\n\n";
}

int main() {
    // set unweighted_matrix to -1
    for (int i = 0; i < nodes; ++i) {
        unweighted_matrix[i].fill(-1);
    }

    cin >> nodes >> edges >> desired_len >> start >> target;

    // organize edge inputs;
    for (int i = 0; i < edges; ++i) {
        // cout << nodes << i << "\n";
        int u, v, w;
        cin >> u >> v >> w;
        // add to edge list
        edge_list.push_back(pair<int, int>(u, adj_list[u].size())); // u, v = adj_list[u][adj_list[u].size()]
        if (w == 0) {
            // add to unweighted list
            unweighted_matrix[u][v] = adj_list[u].size(); // if erased, equals index on adj_list
            unweighted_matrix[v][u] = adj_list[v].size(); // if erased, equals index of adj_list
            // assign weight 1 if erased
            adj_list[u].push_back(pair<int, int>(v, 1));
            adj_list[v].push_back(pair<int, int>(u, 1));
        } else {
            adj_list[u].push_back(pair<int, int>(v, w));
            adj_list[v].push_back(pair<int, int>(u, w));
        }
    }

    // Run Dijkstra's with all erased set to 1.
    dijkstra();
    // cout << "First dijkstra complete\n";

    bool flag = true;
    // while desired length is less than target;
    while (flag && dist[target] < desired_len) {
        flag = false;
        int temp_node = target;
        while (temp_node != start) {
            if (parent[temp_node].second) {
                // adjust edge length if edge is true
                int parent_node = parent[temp_node].first;
                int index = unweighted_matrix[temp_node][parent_node]; // gets the adj_list index
                int parent_index = unweighted_matrix[parent_node][temp_node];
                adj_list[temp_node][index].second = desired_len - dist[target] + 1;
                adj_list[parent_node][parent_index].second = desired_len - dist[target] + 1;
                // set edge as filled
                unweighted_matrix[parent_node][temp_node] = -1;
                unweighted_matrix[temp_node][parent_node] = -1;
                // call dijkstra on updated graph
                dijkstra();
                // break from this loop, but not next
                flag = true;
                break;
            }
            temp_node = parent[temp_node].first;
        }
        if (!flag) break;
    }

    // output
    // cout << dist[target] << " " << desired_len << "\n";
    if (dist[target] == desired_len) {
        // end if true
        cout << "YES\n";
        for (int i = 0; i < edge_list.size(); ++i) {
            int u = edge_list[i].first;
            int v = adj_list[u][edge_list[i].second].first;
            long long int w = adj_list[u][edge_list[i].second].second;
            cout << u << " " << v << " " << w << "\n";
        }
    } else {
        cout << "NO\n";
    }
    return 0;
}


//
//  main.cpp
//  Codeforces
//
//  Created by Luke Zhu on 9/25/16.
//  Copyright © 2016 Luke Zhu. All rights reserved.
//

// Problem D
# include <iostream>
# include <array>
# include <vector>
# include <algorithm>
# include <map>

# define MAX_DIST 100000000000000000

using namespace std;

// Dijkstra O(3.3*10^5) up to 1000 times
// Let adj matrix of erased equal 1
// Get shortest path
// If greater than, print NO
// If less/equal desired, add (desired - length) to erased edges, rerun dijkstra
// Do the above until all erased are filled (NO),
// or until dist = desired (YES)

int nodes, edges, start, target;
long long int desired_len;
map <pair<int, int>, int> erased_map;
array<vector<pair<int, long long int>>, 1000> adj_list; // holds to_node and weight
vector<pair<int, int>> edge_list;
array<bool, 1000> visited;
array<long long int, 1000> dist; // from source
array<int, 1000> parent; // true if an erased node

void dijkstra() {
    // Initialize dijkstra arrays;
    dist.fill(MAX_DIST);
    parent.fill(-1); // parent index, and whether connecting edge is erased
    visited.fill(false);
    dist[start] = 0;

    for (int i = 0; i < nodes; ++i) {
        long long int min_dist = MAX_DIST;
        int closest = -1;
        for (int j = 0; j < nodes; ++j) {
            if (!visited[j] && dist[j] < min_dist) {
                min_dist = dist[j];
                closest = j;
            }
        }
        visited[closest] = true;
        // cout << closest << "\n";

        for (int j = 0; j < adj_list[closest].size(); ++j) {
            int v = adj_list[closest][j].first;
            long long int w = adj_list[closest][j].second;
            if (dist[v] > dist[closest] + w) {
                dist[v] = dist[closest] + w;
                // cout << v << " " << dist[v] << "\n";
                parent[v] = closest;
            }
        }
    }
    // cout << dist[target] << "\n\n";
}

int main() {
    // set unweighted_matrix to -1
    cin >> nodes >> edges >> desired_len >> start >> target;

    // organize edge inputs;
    for (int i = 0; i < edges; ++i) {
        // cout << nodes << i << "\n";
        int u, v, w;
        cin >> u >> v >> w;
        // add to edge list
        edge_list.push_back(pair<int, int>(u, adj_list[u].size())); // u, v = adj_list[u][adj_list[u].size()]
        if (w == 0) {
            // add to erased map
            erased_map[pair<int, int>(u, v)] = adj_list[u].size();
            erased_map[pair<int, int>(v, u)] = adj_list[v].size();
            // assign weight 1 if erased
            adj_list[u].push_back(pair<int, int>(v, 1));
            adj_list[v].push_back(pair<int, int>(u, 1));
        } else {
            adj_list[u].push_back(pair<int, int>(v, w));
            adj_list[v].push_back(pair<int, int>(u, w));
        }
    }

    // Run Dijkstra's with all erased set to 1.
    dijkstra();
    // cout << "First dijkstra complete\n";

    // while desired length is less than target;
    int temp_node = target;
    bool updated = false;
    while (temp_node != -1) {
        // cout << temp_node << " " << parent[temp_node] << "\n";
        int parent_node = parent[temp_node];
        if (erased_map.count(pair<int, int>(temp_node, parent_node))) {
            if (!updated) {
                // adjust edge length if edge is true
                int index = erased_map[pair<int, int>(temp_node, parent_node)]; // gets the adj_list index
                int parent_index = erased_map[pair<int, int>(parent_node, temp_node)];
                adj_list[temp_node][index].second = desired_len - dist[target] + 1;
                adj_list[parent_node][parent_index].second = desired_len - dist[target] + 1;
                updated = true;
            }
            // remove from map
            erased_map.erase(pair<int, int>(temp_node, parent_node));
            erased_map.erase(pair<int, int>(parent_node, temp_node));
        }
        temp_node = parent[temp_node];
    }

    for (auto pair : erased_map) {
        adj_list[pair.first.first][pair.second].second = 1000000000;
    }
    dijkstra();

    // output
    // cout << dist[target] << " " << desired_len << "\n";
    if (dist[target] == desired_len) {
        // end if true
        cout << "YES\n";
        for (int i = 0; i < edge_list.size(); ++i) {
            int u = edge_list[i].first;
            int v = adj_list[u][edge_list[i].second].first;
            long long int w = adj_list[u][edge_list[i].second].second;
            cout << u << " " << v << " " << w << "\n";
        }
    } else {
        cout << "NO\n";
    }
    return 0;
}


//
//  main.cpp
//  Codeforces
//
//  Created by Luke Zhu on 9/25/16.
//  Copyright © 2016 Luke Zhu. All rights reserved.
//

// Problem D
# include <iostream>
# include <array>
# include <vector>
# include <algorithm>
# include <map>

# define MAX_DIST 1000000000000000000

using namespace std;

// Dijkstra O(3.3*10^5) up to 1000 times
// Let adj matrix of erased equal 1
// Get shortest path
// If greater than, print NO
// If less/equal desired, add (desired - length) to erased edges, rerun dijkstra
// Do the above until all erased are filled (NO),
// or until dist = desired (YES)

int nodes, edges, start, target;
long long int desired_len;
array<array<int, 1000>, 1000> unweighted_matrix; // if not -1, equals index on adj list
array<vector<pair<int, long long int>>, 1000> adj_list;
vector<pair<int, int>> edge_list;
array<bool, 1000> visited;
array<long long int, 1000> dist; // from source
array<pair<int, bool>, 1000> parent; // true if an erased node

void dijkstra() {
    // Initialize dijkstra arrays;
    dist.fill(MAX_DIST);
    parent.fill(pair<int, bool>(-1, false));
    visited.fill(false);
    dist[start] = 0;

    for (int i = 0; i < nodes; ++i) {
        long long int min_dist = MAX_DIST;
        int closest = -1;
        for (int j = 0; j < nodes; ++j) {
            if (!visited[j] && dist[j] < min_dist) {
                min_dist = dist[j];
                closest = j;
            }
        }
        visited[closest] = true;
        // cout << closest << "\n";

        for (int j = 0; j < adj_list[closest].size(); ++j) {
            int v = adj_list[closest][j].first;
            long long int w = adj_list[closest][j].second;
            if (dist[v] > dist[closest] + w) {
                dist[v] = dist[closest] + w;
                // cout << v << " " << dist[v] << "\n";
                if (unweighted_matrix[closest][v] != -1) {
                    parent[v] = pair<int, bool>(closest, true);
                } else {
                    parent[v] = pair<int, bool>(closest, false);
                }
            }
        }
    }
    // cout << dist[target] << "\n";
}

int main() {
    // set unweighted_matrix to -1
    for (int i = 0; i < nodes; ++i) {
        unweighted_matrix[i].fill(-1);
    }

    cin >> nodes >> edges >> desired_len >> start >> target;

    // organize edge inputs;
    for (int i = 0; i < edges; ++i) {
        // cout << nodes << i << "\n";
        int u, v, w;
        cin >> u >> v >> w;
        // add to edge list
        edge_list.push_back(pair<int, int>(u, adj_list[u].size()));
        if (w == 0) {
            // add to unweighted list
            unweighted_matrix[u][v] = adj_list[u].size();
            unweighted_matrix[v][u] - adj_list[v].size();
            // assign weight 1 if erased
            adj_list[u].push_back(pair<int, int>(v, 1));
            adj_list[v].push_back(pair<int, int>(u, 1));
        } else {
            adj_list[u].push_back(pair<int, int>(v, w));
            adj_list[v].push_back(pair<int, int>(u, w));
        }
    }
    // cout << "Input ok\n";

    // Run Dijkstra's with all erased set to 1.
    dijkstra();
    // cout << "First dijkstra complete\n";
    bool flag = true;
    // while desired length is less than target;
    while (flag && dist[target] < desired_len) {
        flag = false;
        vector<pair<int, int>> path; // does not contain the target node;
        int temp_node = target;
        while (temp_node != start) {
            path.push_back(parent[temp_node]);
            if (parent[temp_node].second) {
                // adjust edge lengths
                int parent_node = parent[temp_node].first;
                int index = unweighted_matrix[temp_node][parent_node];
                int parent_index = unweighted_matrix[parent_node][temp_node];
                adj_list[temp_node][index].second = desired_len - dist[target] + 1;
                adj_list[parent_node][parent_index].second = desired_len - dist[target] + 1;
                // set edge as filled
                unweighted_matrix[parent_node][temp_node] = -1;
                // call dijkstra on updated graph
                dijkstra();
                // break from this loop, but not next
                flag = true;
                break;
            }
            temp_node = parent[temp_node].first;
        }
        if (!flag) break;
    }

    // output
    // cout << dist[target] << " " << desired_len << "\n";
    if (dist[target] == desired_len) {
        // end if true
        cout << "YES\n";
        for (int i = 0; i < edge_list.size(); ++i) {
            int u = edge_list[i].first;
            int v = adj_list[u][edge_list[i].second].first;
            long long int w = adj_list[u][edge_list[i].second].second;
            cout << u << " " << v << " " << w << "\n";
        }
    } else {
        cout << "NO\n";
    }
    return 0;
}


//
//  main.cpp
//  Codeforces
//
//  Created by Luke Zhu on 9/25/16.
//  Copyright © 2016 Luke Zhu. All rights reserved.
//

// Problem D
# include <iostream>
# include <array>
# include <vector>
# include <algorithm>
# include <map>

# define MAX_DIST 1000000000000000000

using namespace std;

// Dijkstra O(3.3*10^5) up to 1000 times
// Let adj matrix of erased equal 1
// Get shortest path
// If greater than, print NO
// If less/equal desired, add (desired - length) to erased edges, rerun dijkstra
// Do the above until all erased are filled (NO),
// or until dist = desired (YES)

int nodes, edges, start, target;
long long int desired_len;
map <pair<int, int>, int> erased_map;
array<vector<pair<int, long long int>>, 1000> adj_list; // holds to_node and weight
vector<pair<int, int>> edge_list;
array<bool, 1000> visited;
array<long long int, 1000> dist; // from source
array<int, 1000> parent; // true if an erased node

void dijkstra() {
    // Initialize dijkstra arrays;
    dist.fill(MAX_DIST);
    parent.fill(-1); // parent index, and whether connecting edge is erased
    visited.fill(false);
    dist[start] = 0;

    for (int i = 0; i < nodes; ++i) {
        long long int min_dist = MAX_DIST;
        int closest = -1;
        for (int j = 0; j < nodes; ++j) {
            if (!visited[j] && dist[j] < min_dist) {
                min_dist = dist[j];
                closest = j;
            }
        }
        visited[closest] = true;
        // cout << closest << "\n";

        for (int j = 0; j < adj_list[closest].size(); ++j) {
            int v = adj_list[closest][j].first;
            long long int w = adj_list[closest][j].second;
            if (dist[v] > dist[closest] + w) {
                dist[v] = dist[closest] + w;
                // cout << v << " " << dist[v] << "\n";
                if (erased_map.count(pair<int, int>(closest, v))) {
                    parent[v] = closest;
                } else {
                    parent[v] = closest;
                }
            }
        }
    }
    // cout << dist[target] << "\n\n";
}

int main() {
    // set unweighted_matrix to -1
    cin >> nodes >> edges >> desired_len >> start >> target;

    // organize edge inputs;
    for (int i = 0; i < edges; ++i) {
        // cout << nodes << i << "\n";
        int u, v, w;
        cin >> u >> v >> w;
        // add to edge list
        edge_list.push_back(pair<int, int>(u, adj_list[u].size())); // u, v = adj_list[u][adj_list[u].size()]
        if (w == 0) {
            // add to erased map
            erased_map[pair<int, int>(u, v)] = (int) adj_list[u].size();
            erased_map[pair<int, int>(v, u)] = (int) adj_list[v].size();
            // assign weight 1 if erased
            adj_list[u].push_back(pair<int, int>(v, 1));
            adj_list[v].push_back(pair<int, int>(u, 1));
        } else {
            adj_list[u].push_back(pair<int, int>(v, w));
            adj_list[v].push_back(pair<int, int>(u, w));
        }
    }

    // Run Dijkstra's with all erased set to 1.
    dijkstra();
    // cout << "First dijkstra complete\n";

    bool flag = true;
    // while desired length is less than target;
    while (flag && dist[target] < desired_len) {
        flag = false;
        int temp_node = target;
        while (temp_node != start) {
            int parent_node = parent[temp_node];
            if (erased_map.count(pair<int, int>(temp_node, parent_node))) {
                // adjust edge length if edge is true
                int index = erased_map[pair<int, int>(temp_node, parent_node)]; // gets the adj_list index
                int parent_index = erased_map[pair<int, int>(parent_node, temp_node)];
                adj_list[temp_node][index].second = desired_len - dist[target] + 1;
                adj_list[parent_node][parent_index].second = desired_len - dist[target] + 1;
                // call dijkstra on updated graph
                dijkstra();
                // break from this loop, but not next
                flag = true;
                break;
            }
                temp_node = parent[temp_node];
        }
        if (!flag) break;
    }

    // output
    // cout << dist[target] << " " << desired_len << "\n";
    if (dist[target] == desired_len) {
        // end if true
        cout << "YES\n";
        for (int i = 0; i < edge_list.size(); ++i) {
            int u = edge_list[i].first;
            int v = adj_list[u][edge_list[i].second].first;
            long long int w = adj_list[u][edge_list[i].second].second;
            cout << u << " " << v << " " << w << "\n";
        }
    } else {
        cout << "NO\n";
    }
    return 0;
}


//
//  main.cpp
//  Codeforces
//
//  Created by Luke Zhu on 9/25/16.
//  Copyright © 2016 Luke Zhu. All rights reserved.
//

// Problem D
# include <iostream>
# include <array>
# include <vector>
# include <algorithm>
# include <map>

# define MAX_DIST 500000000000000000

using namespace std;

// Dijkstra O(3.3*10^5) up to 1000 times
// Let adj matrix of erased equal 1
// Get shortest path
// If greater than, print NO
// If less/equal desired, add (desired - length) to erased edges, rerun dijkstra
// Do the above until all erased are filled (NO),
// or until dist = desired (YES)

int nodes, edges, start, target;
long long int desired_len;
map <pair<int, int>, int> erased_map;
array<vector<pair<int, long long int>>, 1000> adj_list; // holds to_node and weight
vector<pair<int, int>> edge_list;
array<bool, 1000> visited;
array<long long int, 1000> dist; // from source
array<int, 1000> parent; // true if an erased node

void dijkstra() {
    // Initialize dijkstra arrays;
    dist.fill(MAX_DIST);
    parent.fill(-1); // parent index, and whether connecting edge is erased
    visited.fill(false);
    dist[start] = 0;

    for (int i = 0; i < nodes; ++i) {
        long long int min_dist = MAX_DIST;
        int closest = -1;
        for (int j = 0; j < nodes; ++j) {
            if (!visited[j] && dist[j] < min_dist) {
                min_dist = dist[j];
                closest = j;
            }
        }
        if (closest == -1) continue;
        visited[closest] = true;
        // cout << closest << "\n";

        for (int j = 0; j < adj_list[closest].size(); ++j) {
            int v = adj_list[closest][j].first;
            long long int w = adj_list[closest][j].second;
            if (dist[v] > dist[closest] + w) {
                dist[v] = dist[closest] + w;
                // cout << v << " " << dist[v] << "\n";
                parent[v] = closest;
            }
        }
    }
    // cout << dist[target] << "\n\n";
}

int main() {
    // set unweighted_matrix to -1
    cin >> nodes >> edges >> desired_len >> start >> target;

    // organize edge inputs;
    for (int i = 0; i < edges; ++i) {
        // cout << nodes << i << "\n";
        int u, v, w;
        cin >> u >> v >> w;
        // add to edge list
        edge_list.push_back(pair<int, int>(u, adj_list[u].size())); // u, v = adj_list[u][adj_list[u].size()]
        if (w == 0) {
            // add to erased map
            erased_map[pair<int, int>(u, v)] = adj_list[u].size();
            erased_map[pair<int, int>(v, u)] = adj_list[v].size();
            // assign weight 1 if erased
            adj_list[u].push_back(pair<int, int>(v, 1));
            adj_list[v].push_back(pair<int, int>(u, 1));
        } else {
            adj_list[u].push_back(pair<int, int>(v, w));
            adj_list[v].push_back(pair<int, int>(u, w));
        }
    }

    // Run Dijkstra's with all erased set to 1.
    dijkstra();
    // cout << "First dijkstra complete\n";

    // if desired length is less than target, add weight to edges;
    if (dist[target] < desired_len) {
        int temp_node = target;
        bool updated = false;
        while (temp_node != -1) {
            // cout << temp_node << " " << parent[temp_node] << "\n";
            int parent_node = parent[temp_node];
            if (erased_map.count(pair<int, int>(temp_node, parent_node))) {
                if (!updated) {
                    // adjust edge length if edge is true
                    int index = erased_map[pair<int, int>(temp_node, parent_node)]; // gets the adj_list index
                    int parent_index = erased_map[pair<int, int>(parent_node, temp_node)];
                    adj_list[temp_node][index].second = desired_len - dist[target] + 1;
                    adj_list[parent_node][parent_index].second = desired_len - dist[target] + 1;
                    updated = true;

                    cout << "updated\n" << adj_list[temp_node][index].second << "\n";
                }
                // remove from map
                erased_map.erase(pair<int, int>(temp_node, parent_node));
                erased_map.erase(pair<int, int>(parent_node, temp_node));
            }
            temp_node = parent[temp_node];
        }
    }

    for (auto key_val : erased_map) {
        adj_list[key_val.first.first][key_val.second].second = MAX_DIST;
    }

    dijkstra();

    // output
    // cout << dist[target] << " " << desired_len << "\n";
    if (dist[target] == desired_len) {
        // end if true
        cout << "YES\n";
        for (int i = 0; i < edge_list.size(); ++i) {
            int u = edge_list[i].first;
            int v = adj_list[u][edge_list[i].second].first;
            long long int w = adj_list[u][edge_list[i].second].second;
            cout << u << " " << v << " " << w << "\n";
        }
    } else {
        cout << "NO\n";
    }
    return 0;
}


//
//  main.cpp
//  Codeforces
//
//  Created by Luke Zhu on 9/25/16.
//  Copyright © 2016 Luke Zhu. All rights reserved.
//

// Problem D
# include <iostream>
# include <array>
# include <vector>
# include <algorithm>
# include <map>

# define MAX_DIST 500000000000000000

using namespace std;

// Dijkstra O(3.3*10^5) up to 1000 times
// Let adj matrix of erased equal 1
// Get shortest path
// If greater than, print NO
// If less/equal desired, add (desired - length) to erased edges, rerun dijkstra
// Do the above until all erased are filled (NO),
// or until dist = desired (YES)

int nodes, edges, start, target;
long long int desired_len;
map <pair<int, int>, int> erased_map;
array<vector<pair<int, long long int>>, 1000> adj_list; // holds to_node and weight
vector<pair<int, int>> edge_list;
array<bool, 1000> visited;
array<long long int, 1000> dist; // from source
array<int, 1000> parent; // true if an erased node

void dijkstra() {
    // Initialize dijkstra arrays;
    dist.fill(MAX_DIST);
    parent.fill(-1); // parent index, and whether connecting edge is erased
    visited.fill(false);
    dist[start] = 0;

    for (int i = 0; i < nodes; ++i) {
        long long int min_dist = MAX_DIST;
        int closest = -1;
        for (int j = 0; j < nodes; ++j) {
            if (!visited[j] && dist[j] < min_dist) {
                min_dist = dist[j];
                closest = j;
            }
        }
        if (closest == -1) continue;
        visited[closest] = true;
        // cout << closest << "\n";

        for (int j = 0; j < adj_list[closest].size(); ++j) {
            int v = adj_list[closest][j].first;
            long long int w = adj_list[closest][j].second;
            if (dist[v] > dist[closest] + w) {
                dist[v] = dist[closest] + w;
                // cout << v << " " << dist[v] << "\n";
                parent[v] = closest;
            }
        }
    }
    // cout << dist[target] << "\n\n";
}

int main() {
    // set unweighted_matrix to -1
    cin >> nodes >> edges >> desired_len >> start >> target;

    // organize edge inputs;
    for (int i = 0; i < edges; ++i) {
        // cout << nodes << i << "\n";
        int u, v, w;
        cin >> u >> v >> w;
        // add to edge list
        edge_list.push_back(pair<int, int>(u, adj_list[u].size())); // u, v = adj_list[u][adj_list[u].size()]
        if (w == 0) {
            // add to erased map
            erased_map[pair<int, int>(u, v)] = adj_list[u].size();
            erased_map[pair<int, int>(v, u)] = adj_list[v].size();
            // assign weight 1 if erased
            adj_list[u].push_back(pair<int, int>(v, 1));
            adj_list[v].push_back(pair<int, int>(u, 1));
        } else {
            adj_list[u].push_back(pair<int, int>(v, w));
            adj_list[v].push_back(pair<int, int>(u, w));
        }
    }

    // Run Dijkstra's with all erased set to 1.
    dijkstra();
    // cout << "First dijkstra complete\n";

    // if desired length is less than target, add weight to edges;
    if (desired_len > dist[target]) {
        int temp_node = target;
        bool updated = false;
        while (temp_node != -1) {
            // cout << temp_node << " " << parent[temp_node] << "\n";
            int parent_node = parent[temp_node];
            if (erased_map.count(pair<int, int>(temp_node, parent_node))) {
                if (!updated) {
                    // cout << "updated\n";
                    // adjust edge length if edge is true
                    int index = erased_map[pair<int, int>(temp_node, parent_node)]; // gets the adj_list index
                    int parent_index = erased_map[pair<int, int>(parent_node, temp_node)];
                    adj_list[temp_node][index].second = desired_len - dist[target] + 1;
                    adj_list[parent_node][parent_index].second = desired_len - dist[target] + 1;
                    updated = true;
                }
                // remove from map
                erased_map.erase(pair<int, int>(temp_node, parent_node));
                erased_map.erase(pair<int, int>(parent_node, temp_node));
            }
            temp_node = parent[temp_node];
        }
    }

    dijkstra();

    // output
    // cout << dist[target] << " " << desired_len << "\n";
    if (dist[target] == desired_len) {
        // end if true
        cout << "YES\n";
        for (int i = 0; i < edge_list.size(); ++i) {
            int u = edge_list[i].first;
            int v = adj_list[u][edge_list[i].second].first;
            long long int w = adj_list[u][edge_list[i].second].second;
            cout << u << " " << v << " " << w << "\n";
        }
    } else {
        cout << "NO\n";
    }
    return 0;
}


//
//  main.cpp
//  Codeforces
//
//  Created by Luke Zhu on 9/25/16.
//  Copyright © 2016 Luke Zhu. All rights reserved.
//

// Problem D
# include <iostream>
# include <array>
# include <vector>
# include <algorithm>
# include <map>

# define MAX_DIST 1000000000000000000

using namespace std;

// Dijkstra O(3.3*10^5) up to 1000 times
// Let adj matrix of erased equal 1
// Get shortest path
// If greater than, print NO
// If less/equal desired, add (desired - length) to erased edges, rerun dijkstra
// Do the above until all erased are filled (NO),
// or until dist = desired (YES)

int nodes, edges, start, target;
long long int desired_len;
array<array<int, 1000>, 1000> unweighted_matrix; // if not -1, equals index on adj list
array<vector<pair<int, long long int>>, 1000> adj_list;
vector<pair<int, int>> edge_list;
array<bool, 1000> visited;
array<long long int, 1000> dist; // from source
array<pair<int, bool>, 1000> parent; // true if an erased node

void dijkstra() {
    // Initialize dijkstra arrays;
    dist.fill(MAX_DIST);
    parent.fill(pair<int, bool>(-1, false));

    dist[start] = 0;

    for (int i = 0; i < nodes; ++i) {
        long long int min_dist = MAX_DIST;
        int closest = -1;
        for (int j = 0; j < nodes; ++j) {
            if (!visited[j] && dist[j] < min_dist) {
                min_dist = dist[j];
                closest = j;
                visited[j] = true;
            }
        }
        for (int j = 0; j < adj_list[closest].size(); ++j) {
            int v = adj_list[closest][j].first;
            long long int w = adj_list[closest][j].second;
            if (dist[v] > dist[closest] + w) {
                dist[v] = dist[closest] + w;
                // cout << v << " " << dist[v] << "\n";
                if (unweighted_matrix[closest][v] != -1) {
                    parent[v] = pair<int, bool>(closest, true);
                } else {
                    parent[v] = pair<int, bool>(closest, false);
                }
            }
        }
    }
    // cout << dist[target] << "\n";
}

int main() {
    // set unweighted_matrix to -1
    for (int i = 0; i < nodes; ++i) {
        unweighted_matrix[i].fill(-1);
    }

    cin >> nodes >> edges >> desired_len >> start >> target;

    // organize edge inputs;
    for (int i = 0; i < edges; ++i) {
        // cout << nodes << i << "\n";
        int u, v, w;
        cin >> u >> v >> w;
        // add to edge list
        edge_list.push_back(pair<int, int>(u, adj_list[u].size()));
        if (w == 0) {
            // add to unweighted list
            unweighted_matrix[u][v] = adj_list[u].size();
            unweighted_matrix[v][u] - adj_list[v].size();
            // assign weight 1 if erased
            adj_list[u].push_back(pair<int, int>(v, 1));
            adj_list[v].push_back(pair<int, int>(u, 1));
        } else {
            adj_list[u].push_back(pair<int, int>(v, w));
            adj_list[v].push_back(pair<int, int>(u, w));
        }
    }
    // cout << "Input ok\n";

    // Run Dijkstra's with all erased set to 1.
    dijkstra();
    // cout << "First dijkstra complete\n";
    bool flag = true;
    // while desired length is less than target;
    while (flag && dist[target] < desired_len) {
        flag = false;
        vector<pair<int, int>> path; // does not contain the target node;
        int temp_node = target;
        while (temp_node != start) {
            path.push_back(parent[temp_node]);
            if (parent[temp_node].second) {
                // adjust edge lengths
                int parent_node = parent[temp_node].first;
                int index = unweighted_matrix[temp_node][parent_node];
                int parent_index = unweighted_matrix[parent_node][temp_node];
                adj_list[temp_node][index].second = desired_len - dist[target] + 1;
                adj_list[parent_node][parent_index].second = desired_len - dist[target] + 1;
                // set edge as filled
                unweighted_matrix[parent_node][temp_node] = -1;
                // call dijkstra on updated graph
                dijkstra();
                // break from this loop, but not next
                flag = true;
                break;
            }
            temp_node = parent[temp_node].first;
        }
        if (!flag) break;
    }

    // output
    cout << dist[target] << " " << desired_len << "\n";
    if (dist[target] == desired_len) {
        // end if true
        cout << "YES\n";
        for (int i = 0; i < edge_list.size(); ++i) {
            int u = edge_list[i].first;
            int v = adj_list[u][edge_list[i].second].first;
            long long int w = adj_list[u][edge_list[i].second].second;
            cout << u << " " << v << " " << w << "\n";
        }
    } else {
        cout << "NO\n";
    }
    return 0;
}


//
//  main.cpp
//  Codeforces
//
//  Created by Luke Zhu on 9/25/16.
//  Copyright © 2016 Luke Zhu. All rights reserved.
//

// Problem D
# include <iostream>
# include <array>
# include <vector>
# include <algorithm>
# include <map>

# define MAX_DIST 1000000000000000000

using namespace std;

// Dijkstra O(3.3*10^5) up to 1000 times
// Let adj matrix of erased equal 1
// Get shortest path
// If greater than, print NO
// If less/equal desired, add (desired - length) to erased edges, rerun dijkstra
// Do the above until all erased are filled (NO),
// or until dist = desired (YES)

int nodes, edges, start, target;
long long int desired_len;
map <pair<int, int>, int> erased_map;
array<vector<pair<int, long long int>>, 1000> adj_list; // holds to_node and weight
vector<pair<int, int>> edge_list;
array<bool, 1000> visited;
array<long long int, 1000> dist; // from source
array<int, 1000> parent; // true if an erased node

void dijkstra() {
    // Initialize dijkstra arrays;
    dist.fill(MAX_DIST);
    parent.fill(-1); // parent index, and whether connecting edge is erased
    visited.fill(false);
    dist[start] = 0;

    for (int i = 0; i < nodes; ++i) {
        long long int min_dist = MAX_DIST;
        int closest = -1;
        for (int j = 0; j < nodes; ++j) {
            if (!visited[j] && dist[j] < min_dist) {
                min_dist = dist[j];
                closest = j;
            }
        }
        visited[closest] = true;
        // cout << closest << "\n";

        for (int j = 0; j < adj_list[closest].size(); ++j) {
            int v = adj_list[closest][j].first;
            long long int w = adj_list[closest][j].second;
            if (dist[v] > dist[closest] + w) {
                dist[v] = dist[closest] + w;
                // cout << v << " " << dist[v] << "\n";
                parent[v] = closest;
            }
        }
    }
    // cout << dist[target] << "\n\n";
}

int main() {
    // set unweighted_matrix to -1
    cin >> nodes >> edges >> desired_len >> start >> target;

    // organize edge inputs;
    for (int i = 0; i < edges; ++i) {
        // cout << nodes << i << "\n";
        int u, v, w;
        cin >> u >> v >> w;
        // add to edge list
        edge_list.push_back(pair<int, int>(u, adj_list[u].size())); // u, v = adj_list[u][adj_list[u].size()]
        if (w == 0) {
            // add to erased map
            erased_map[pair<int, int>(u, v)] = adj_list[u].size();
            erased_map[pair<int, int>(v, u)] = adj_list[v].size();
            // assign weight 1 if erased
            adj_list[u].push_back(pair<int, int>(v, 1));
            adj_list[v].push_back(pair<int, int>(u, 1));
        } else {
            adj_list[u].push_back(pair<int, int>(v, w));
            adj_list[v].push_back(pair<int, int>(u, w));
        }
    }

    // Run Dijkstra's with all erased set to 1.
    dijkstra();
    // cout << "First dijkstra complete\n";

    // while desired length is less than target;
    int temp_node = target;
    bool updated = false;
    while (temp_node != -1) {
        cout << temp_node << " " << parent[temp_node] << "\n";
        int parent_node = parent[temp_node];
        if (erased_map.count(pair<int, int>(temp_node, parent_node))) {
            if (!updated) {
                // adjust edge length if edge is true
                int index = erased_map[pair<int, int>(temp_node, parent_node)]; // gets the adj_list index
                int parent_index = erased_map[pair<int, int>(parent_node, temp_node)];
                adj_list[temp_node][index].second = desired_len - dist[target] + 1;
                adj_list[parent_node][parent_index].second = desired_len - dist[target] + 1;
                updated = true;
            }
            // remove from map
            erased_map.erase(pair<int, int>(temp_node, parent_node));
            erased_map.erase(pair<int, int>(parent_node, temp_node));
        }
        temp_node = parent[temp_node];
    }

    for (auto pair : erased_map) {
        adj_list[pair.first.first][pair.second].second = 1000000000;
    }
    dijkstra();

    // output
    cout << dist[target] << " " << desired_len << "\n";
    if (dist[target] == desired_len) {
        // end if true
        cout << "YES\n";
        for (int i = 0; i < edge_list.size(); ++i) {
            int u = edge_list[i].first;
            int v = adj_list[u][edge_list[i].second].first;
            long long int w = adj_list[u][edge_list[i].second].second;
            cout << u << " " << v << " " << w << "\n";
        }
    } else {
        cout << "NO\n";
    }
    return 0;
}


//
//  main.cpp
//  Codeforces
//
//  Created by Luke Zhu on 9/25/16.
//  Copyright © 2016 Luke Zhu. All rights reserved.
//

// Problem D
# include <iostream>
# include <array>
# include <vector>
# include <algorithm>
# include <map>

# define MAX_DIST 500000000000000000

using namespace std;

// Dijkstra O(3.3*10^5) up to 1000 times
// Let adj matrix of erased equal 1
// Get shortest path
// If greater than, print NO
// If less/equal desired, add (desired - length) to erased edges, rerun dijkstra
// Do the above until all erased are filled (NO),
// or until dist = desired (YES)

int nodes, edges, start, target;
long long int desired_len;
map <pair<int, int>, int> erased_map;
array<vector<pair<int, long long int>>, 1000> adj_list; // holds to_node and weight
vector<pair<int, int>> edge_list;
array<bool, 1000> visited;
array<long long int, 1000> dist; // from source
array<int, 1000> parent; // true if an erased node

void dijkstra() {
    // Initialize dijkstra arrays;
    dist.fill(MAX_DIST);
    parent.fill(-1); // parent index, and whether connecting edge is erased
    visited.fill(false);
    dist[start] = 0;

    for (int i = 0; i < nodes; ++i) {
        long long int min_dist = MAX_DIST;
        int closest = -1;
        for (int j = 0; j < nodes; ++j) {
            if (!visited[j] && dist[j] < min_dist) {
                min_dist = dist[j];
                closest = j;
            }
        }
        if (closest == -1) continue;
        visited[closest] = true;
        // cout << closest << "\n";

        for (int j = 0; j < adj_list[closest].size(); ++j) {
            int v = adj_list[closest][j].first;
            long long int w = adj_list[closest][j].second;
            if (dist[v] > dist[closest] + w) {
                dist[v] = dist[closest] + w;
                // cout << v << " " << dist[v] << "\n";
                parent[v] = closest;
            }
        }
    }
    // cout << dist[target] << "\n\n";
}

int main() {
    // set unweighted_matrix to -1
    cin >> nodes >> edges >> desired_len >> start >> target;

    // organize edge inputs;
    for (int i = 0; i < edges; ++i) {
        // cout << nodes << i << "\n";
        int u, v, w;
        cin >> u >> v >> w;
        // add to edge list
        edge_list.push_back(pair<int, int>(u, adj_list[u].size())); // u, v = adj_list[u][adj_list[u].size()]
        if (w == 0) {
            // add to erased map
            erased_map[pair<int, int>(u, v)] = adj_list[u].size();
            erased_map[pair<int, int>(v, u)] = adj_list[v].size();
            // assign weight 1 if erased
            adj_list[u].push_back(pair<int, int>(v, 1));
            adj_list[v].push_back(pair<int, int>(u, 1));
        } else {
            adj_list[u].push_back(pair<int, int>(v, w));
            adj_list[v].push_back(pair<int, int>(u, w));
        }
    }

    // Run Dijkstra's with all erased set to 1.
    dijkstra();

    map<pair<int, int>, int> temp_map;
    // if desired length is less than target, add weight to edges;
    bool updated = true;
    while (updated && dist[target] < desired_len) {
        int temp_node = target;
        updated = false;
        while (temp_node != -1) {
            // cout << temp_node << " " << parent[temp_node] << "\n";
            int parent_node = parent[temp_node];
            if (erased_map.count(pair<int, int>(temp_node, parent_node))) {
                if (!updated) {
                    // adjust edge length if edge is true
                    int index = erased_map[pair<int, int>(temp_node, parent_node)]; // gets the adj_list index
                    int parent_index = erased_map[pair<int, int>(parent_node, temp_node)];
                    adj_list[temp_node][index].second = desired_len - dist[target] + 1;
                    adj_list[parent_node][parent_index].second = desired_len - dist[target] + 1;
                    updated = true;

                    // cout << "updated\n" << adj_list[temp_node][index].second << "\n";
                }
                // remove from map
                temp_map[pair<int, int>(temp_node, parent_node)] = erased_map[pair<int, int>(temp_node, parent_node)];
                erased_map.erase(pair<int, int>(temp_node, parent_node));
                temp_map[pair<int, int>(parent_node, temp_node)] = erased_map[pair<int, int>(parent_node, temp_node)];
                erased_map.erase(pair<int, int>(parent_node, temp_node));
            }
            temp_node = parent[temp_node];
        }
        for (auto key_val : erased_map) {
            adj_list[key_val.first.first][key_val.second].second = MAX_DIST;
        }
        erased_map = temp_map;
        dijkstra();
        if (!updated) break;
    }

    // output
    // cout << dist[target] << " " << desired_len << "\n";
    if (dist[target] == desired_len) {
        // end if true
        cout << "YES\n";
        for (int i = 0; i < edge_list.size(); ++i) {
            int u = edge_list[i].first;
            int v = adj_list[u][edge_list[i].second].first;
            long long int w = adj_list[u][edge_list[i].second].second;
            cout << u << " " << v << " " << w << "\n";
        }
    } else {
        cout << "NO\n";
    }
    return 0;
}


import sys

n,m,l,s,t = map(int,sys.stdin.readline().split())

dis = [ 0 for i in xrange(n+3) ]
vis = [ 0 for i in xrange(n+3) ]
U   = [ 0 for i in xrange(m+3) ]
V   = [ 0 for i in xrange(m+3) ]
W   = [ 0 for i in xrange(m+3) ]
OK  = [ 0 for i in xrange(m+3) ]
que = [ 0 for i in xrange(n+3) ]
adj = [ [] for i in xrange(n+3) ]

def Init(n):
    for i in range(n):
        dis[i] = 2**60
        vis[i] = 0

def SPFA(s,n):
    Init(n)
    f = 1
    r = 0

    dis[s] = 0
    vis[s] = 1
    r+=1
    que[r] = s

    while f <= r:
        u = que[f]
        f += 1

        vis[s] = 0

        sz = len(adj[u])
        for i in range(0,sz,2):
            v = adj[u][i]
            _id = adj[u][i+1]
            w = W[_id]

            if dis[v] > dis[u] + w:
                dis[v] = dis[u] + w

                if vis[v] == 0:
                    vis[v] = 1
                    r += 1
                    que[r] = v

for i in range(m):
    u,v,w = map(int,sys.stdin.readline().split())

    U[i] = u
    V[i] = v
    W[i] = w

    if W[i] == 0:
        OK[i] = 1
        W[i] = 2000000000

    adj[u].append(v)
    adj[u].append(i)

    adj[v].append(u)
    adj[v].append(i)

SPFA(s,n)
worst = dis[t]

if l > worst:
    print "NO"
    sys.exit()

best = 2000000000000

for i in range(m):
    if OK[i] == 0:
        continue

    W[i] = 1
    SPFA(s,n)
    best = min(best,dis[t])
    #print i,": ",dis[t]
    if dis[t] <= l:
        W[i] += l-dis[t]
        break

print "YES"

for i in range(m):
    sys.stdout.write(str(U[i])+ " " + str(V[i]) + " " + str(W[i]) + "\n")


/*****************************************************************
 *                   BISMILLAHIR RAHMANIR RAHIM                  *
 *          Raihat Zaman Neloy                                   *
 *          JU-CSE-21                                            *
 *          raihatneloy                                          *
 *****************************************************************/

#include<bits/stdc++.h>

//#include<algorithm>
//#include<cstdio>
//#include<sstream>
//#include<cstdlib>
//#include<cctype>
//#include<cmath>
//#include<set>
//#include<queue>
//#include<stack>
//#include<list>
//#include<iostream>
//#include<fstream>
//#include<numeric>
//#include<string>
//#include<vector>
//#include<cstring>
//#include<map>
//#include<iterator>
//#include<deque>
//#include<climits>
//#include<complex>

#define S scanf
#define P printf

#define LL long long int
#define ULL unsigned long long int
#define D double

#define SQR(n)      (n*n)
#define PI          2.0*acos(0.0)

#define all(a) a.begin(),a.end()
#define X  first
#define Y  second
#define MP make_pair
#define NL P("\n")

#define open       freopen("input.txt","r",stdin)
#define close      freopen ("output.txt","w",stdout)
#define S1(a)      scanf("%d",&a)
#define S2(a,b)    scanf("%d%d",&a,&b)
#define S3(a,b,c)  scanf("%d%d%d",&a,&b,&c)
#define SL1(a)     scanf("%lld",&a)
#define SL2(a,b)   scanf("%lld%lld",&a,&b)
#define SL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define CHR        getchar()
#define PB(x)      push_back(x)
#define pb         push_back
#define PP         pop_back()
#define PF(x)      push_front(x)
#define PPF(x)     pop_front()
#define PS(x)      push(x)
#define sz()       size()
#define UB         upper_bound
#define LB         lower_bound
#define mxe(a,n)   (*max_element(a,a+n))
#define mne(a,n)   (*min_element(a,a+n))
#define SUM(a,n)   (accumulate(a,a+n,0))
#define countbit(x) __builtin_popcount(x)
#define DBG(n)      P("Done %d\n",n);

// I/O
#define I(X)                       scanf("%d", &(X))
#define II(X, Y)                   scanf("%d%d", &(X), &(Y))
#define III(X, Y, Z)               scanf("%d%d%d", &(X), &(Y), &(Z))
#define DI(X) int (X);             scanf("%d", &X)
#define DII(X, Y) int X, Y;        scanf("%d%d", &X, &Y)
#define DIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)

#define ILL(X)          scanf("%lld", &(X))
#define DILL(X) LL (X); scanf("%lld", &X)

// LOOP
#define repv(i,a) for(int i=0;i<(int)a.size();i++)
#define revv(i,a) for(int i=((int)a.size())-1;i>=0;i--)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rev(i,a,b) for(int i=a;i>=b;i--)

#define FS(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++)

#define MEM(a,val) memset(a,val,sizeof(a));
#define SET(a)     memset(a,-1,sizeof a)
#define CLR(a)     memset(a,0,sizeof a)
#define CMPL       cerr<< "Compilation Process Finished\n";cerr<< "----------------------------\n"

using namespace std;

template <typename T> T BigMod (T b,T p,T m){if (p == 0) return 1;if (p%2 == 0){T s = BigMod(b,p/2,m);return ((s%m)*(s%m))%m;}return ((b%m)*(BigMod(b,p-1,m)%m))%m;}
template <typename T> T ModInv (T b,T m){return BigMod(b,m-2,m);}
template <typename T> T in(){char ch;T n = 0;bool ng = false;while (1){ch = getchar();if (ch == '-'){ng = true;ch = getchar();break;}if (ch>='0' && ch<='9')     break;}while (1){n = n*10 + (ch - '0');ch = getchar();if (ch<'0' || ch>'9')   break;}return (ng?-n:n);}
template <typename T> T POW(T B,T P){ if(P==0) return 1; if(P&1) return B*POW(B,P-1);  else return SQR(POW(B,P/2));}
template <typename T> T Bigmod(T b,T p,T m){ if(p==0) return 1; else if (!(p&1)) return SQR(Bigmod(b,p/2,m)) % m;else return ((b % m) * Bigmod(b,p-1,m)) % m;}
template <typename T> T Dis(T x1,T y1,T x2, T y2){return sqrt( SQR(x1-x2) + SQR(y1-y2) );}
template <typename T> T Angle(T x1,T y1,T x2, T y2){ return atan( double(y1-y2) / double(x1-x2));}
template <typename T> T DIFF(T a,T b) { T d = a-b;if(d<0)return -d;else return d;}
template <typename T> T ABS(T a) {if(a<0)return -a;else return a;}
template <typename T> T gcd(T a,T b){if(a<0)return gcd(-a,b);if(b<0)return gcd(a,-b);return (b==0)?a:gcd(b,a%b);}
template <typename T> T lcm(T a,T b) {if(a<0)return lcm(-a,b);if(b<0)return lcm(a,-b);return a*(b/gcd(a,b));}
template <typename T> T euclide(T a,T b,T &x,T &y) {if(a<0){T d=euclide(-a,b,x,y);x=-x;return d;}   if(b<0){T d=euclide(a,-b,x,y);y=-y;return d;}   if(b==0){x=1;y=0;return a;}else{T d=euclide(b,a%b,x,y);T t=x;x=y;y=t-(a/b)*y;return d;}}
template <typename T> void ia (T a[],int n){for (int i=0; i<n; i++) cin >> a[i];}
template <typename T> void pa (T a[],int n){for (int i=0; i<n-1; i++) cout << a[i] << " ";cout << a[n-1] << endl;}
template <typename T> LL isLeft(T a,T b,T c) { return (a.x-b.x)*(b.y-c.y)-(b.x-c.x)*(a.y-b.y); }

int    Set(int N,int pos){ return N=N | (1<<pos);}
int  Reset(int N,int pos){return N= N & ~(1<<pos);}
bool Check(int N,int pos){return (bool)(N & (1<<pos));}
template< class T, class X > inline T   togglebit(T a, X i) { T t=1;return (a^(t<<i)); }

double DEG(double x) { return (180.0*x)/(PI);}
double RAD(double x) { return (x*(double)PI)/(180.0);}

#define VI  vector< int >
#define VII vector< VI >
#define VLL vector< LL >
#define PII pair< int , int >
#define PLL pair< LL , LL >
#define VPI vector< PII >

///         0123456789
#define MX  100007
#define MOD 1000000007
#define INF (1<<30)-1+(1<<30)
#define eps 1e-9

#define base ((1<<l)-1)
#define lft (idx<<1)
#define rgt (lft|1)
#define mid ((l+r)>>1)

/// Hashing Bases & MOD
///           0123456789
#define Base1 10000019ULL
#define Base2 10000079ULL
#define Base3 10000103ULL
#define MOD1  1000000007ULL
#define MOD2  1000000009ULL
#define MOD3  1000000021ULL
#define LOGX  17
#define FCIN  ios_base::sync_with_stdio(0); cin.tie(0)

LL dis[1007][10007];
short par[1007][10007];
short del[1007][10007];
bool vis[1007][10007];
VI adj[MX];
pair< PII , int > edge[10007];

void SPFA(int s){
    queue<int>q;

    q.PS(s);
    q.PS(0);

    vis[s][0] = 1;
    par[s][0] = -1;
    dis[s][0] = 0;

    while(!q.empty()){
        int u = q.front();q.pop();
        int x = q.front();q.pop();

        vis[u][x] = 0;

        for (int i=0;i<adj[u].size();i+=3){
            int v = adj[u][i];
            int w = adj[u][i+1];
            int id = adj[u][i+2];

            if (dis[v][x+(w==0)] > dis[u][x]+w){
                dis[v][x+(w==0)] = dis[u][x]+w;
                par[v][x+(w==0)] = u;
                del[v][x+(w==0)] = id;

                if (!vis[v][x+(w==0)]){
                    q.PS(v);
                    q.PS(x+(w==0));
                    vis[v][x+(w==0)] = 1;
                }
            }
        }
    }
}

void Init(int n,int m){
    for (int i=0;i<=n;i++){
        for (int j=0;j<=m;j++){
            dis[i][j] = 1LL<<60;
        }
    }
}

int main(){
    //cout << sizeof(dis)/1e6 << endl;
    //cout << sizeof(par)/1e6 << endl;
    //cout << sizeof(del)/1e6 << endl;
    //cout << sizeof(vis)/1e6 << endl;

    DII(n,m);
    DIII(l,s,t);

    Init(n,m);

    for (int i=1;i<=m;i++){
        DIII(u,v,w);

        adj[u].PB(v);
        adj[u].PB(w);
        adj[u].PB(i);

        adj[v].PB(u);
        adj[v].PB(w);
        adj[v].PB(i);

        edge[i] = MP( MP(u,v),w );
    }

    SPFA(s);

    if (dis[t][0] == l){
        LL lim = 1000000000000000000LL;

        puts("YES");
        for (int i=1;i<=n;i++){
            P("%d %d ",edge[i].X.X,edge[i].X.Y);

            if (edge[i].Y == 0) P("%lld\n",lim);
            else                P("%d\n",edge[i].Y);
        }

        return 0;
    }

    for (int i=1;i<=m;i++){
        if (l - dis[t][i] < i)  continue;

        VI xx;

        int u = t, x = i;
        //cout << "Path:\n";
        while(par[u][x] != -1){
            //cout << u << ": " << x << endl;
            int id = del[u][x];
            //cout << id << endl;
            if (edge[id].Y == 0){
                //cout << "Dhuklo\n";
                xx.PB(id);
            }

            u = par[u][x];
            if (edge[id].Y == 0)
                x --;
        }
        //cout << "--------\n";

        int baki = l - dis[t][i];

        for (int j=0;j<xx.size();j++){
            //cout << "-> " << xx[j] << endl;
            edge[ xx[j] ].Y = 1;
            baki --;
        }

        edge[ xx.back() ].Y += baki;

        puts("YES");
        for (int j=1;j<=m;j++){
            assert(edge[j].Y <= 1000000000000000000LL);
            P("%d %d %d\n",edge[j].X.X, edge[j].X.Y, edge[j].Y);
        }

        return 0;
    }

    puts("NO");
return 0;
}
/*
5 2 13 0 4
0 1 5
2 1 0
*/


/*****************************************************************
 *                   BISMILLAHIR RAHMANIR RAHIM                  *
 *          Raihat Zaman Neloy                                   *
 *          JU-CSE-21                                            *
 *          raihatneloy                                          *
 *****************************************************************/

#include<bits/stdc++.h>

//#include<algorithm>
//#include<cstdio>
//#include<sstream>
//#include<cstdlib>
//#include<cctype>
//#include<cmath>
//#include<set>
//#include<queue>
//#include<stack>
//#include<list>
//#include<iostream>
//#include<fstream>
//#include<numeric>
//#include<string>
//#include<vector>
//#include<cstring>
//#include<map>
//#include<iterator>
//#include<deque>
//#include<climits>
//#include<complex>

#define S scanf
#define P printf

#define LL long long int
#define ULL unsigned long long int
#define D double

#define SQR(n)      (n*n)
#define PI          2.0*acos(0.0)

#define all(a) a.begin(),a.end()
#define X  first
#define Y  second
#define MP make_pair
#define NL P("\n")

#define open       freopen("input.txt","r",stdin)
#define close      freopen ("output.txt","w",stdout)
#define S1(a)      scanf("%d",&a)
#define S2(a,b)    scanf("%d%d",&a,&b)
#define S3(a,b,c)  scanf("%d%d%d",&a,&b,&c)
#define SL1(a)     scanf("%lld",&a)
#define SL2(a,b)   scanf("%lld%lld",&a,&b)
#define SL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define CHR        getchar()
#define PB(x)      push_back(x)
#define pb         push_back
#define PP         pop_back()
#define PF(x)      push_front(x)
#define PPF(x)     pop_front()
#define PS(x)      push(x)
#define sz()       size()
#define UB         upper_bound
#define LB         lower_bound
#define mxe(a,n)   (*max_element(a,a+n))
#define mne(a,n)   (*min_element(a,a+n))
#define SUM(a,n)   (accumulate(a,a+n,0))
#define countbit(x) __builtin_popcount(x)
#define DBG(n)      P("Done %d\n",n);

// I/O
#define I(X)                       scanf("%d", &(X))
#define II(X, Y)                   scanf("%d%d", &(X), &(Y))
#define III(X, Y, Z)               scanf("%d%d%d", &(X), &(Y), &(Z))
#define DI(X) int (X);             scanf("%d", &X)
#define DII(X, Y) int X, Y;        scanf("%d%d", &X, &Y)
#define DIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)

#define ILL(X)          scanf("%lld", &(X))
#define DILL(X) LL (X); scanf("%lld", &X)

// LOOP
#define repv(i,a) for(int i=0;i<(int)a.size();i++)
#define revv(i,a) for(int i=((int)a.size())-1;i>=0;i--)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rev(i,a,b) for(int i=a;i>=b;i--)

#define FS(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++)

#define MEM(a,val) memset(a,val,sizeof(a));
#define SET(a)     memset(a,-1,sizeof a)
#define CLR(a)     memset(a,0,sizeof a)
#define CMPL       cerr<< "Compilation Process Finished\n";cerr<< "----------------------------\n"

using namespace std;

template <typename T> T BigMod (T b,T p,T m){if (p == 0) return 1;if (p%2 == 0){T s = BigMod(b,p/2,m);return ((s%m)*(s%m))%m;}return ((b%m)*(BigMod(b,p-1,m)%m))%m;}
template <typename T> T ModInv (T b,T m){return BigMod(b,m-2,m);}
template <typename T> T in(){char ch;T n = 0;bool ng = false;while (1){ch = getchar();if (ch == '-'){ng = true;ch = getchar();break;}if (ch>='0' && ch<='9')     break;}while (1){n = n*10 + (ch - '0');ch = getchar();if (ch<'0' || ch>'9')   break;}return (ng?-n:n);}
template <typename T> T POW(T B,T P){ if(P==0) return 1; if(P&1) return B*POW(B,P-1);  else return SQR(POW(B,P/2));}
template <typename T> T Bigmod(T b,T p,T m){ if(p==0) return 1; else if (!(p&1)) return SQR(Bigmod(b,p/2,m)) % m;else return ((b % m) * Bigmod(b,p-1,m)) % m;}
template <typename T> T Dis(T x1,T y1,T x2, T y2){return sqrt( SQR(x1-x2) + SQR(y1-y2) );}
template <typename T> T Angle(T x1,T y1,T x2, T y2){ return atan( double(y1-y2) / double(x1-x2));}
template <typename T> T DIFF(T a,T b) { T d = a-b;if(d<0)return -d;else return d;}
template <typename T> T ABS(T a) {if(a<0)return -a;else return a;}
template <typename T> T gcd(T a,T b){if(a<0)return gcd(-a,b);if(b<0)return gcd(a,-b);return (b==0)?a:gcd(b,a%b);}
template <typename T> T lcm(T a,T b) {if(a<0)return lcm(-a,b);if(b<0)return lcm(a,-b);return a*(b/gcd(a,b));}
template <typename T> T euclide(T a,T b,T &x,T &y) {if(a<0){T d=euclide(-a,b,x,y);x=-x;return d;}   if(b<0){T d=euclide(a,-b,x,y);y=-y;return d;}   if(b==0){x=1;y=0;return a;}else{T d=euclide(b,a%b,x,y);T t=x;x=y;y=t-(a/b)*y;return d;}}
template <typename T> void ia (T a[],int n){for (int i=0; i<n; i++) cin >> a[i];}
template <typename T> void pa (T a[],int n){for (int i=0; i<n-1; i++) cout << a[i] << " ";cout << a[n-1] << endl;}
template <typename T> LL isLeft(T a,T b,T c) { return (a.x-b.x)*(b.y-c.y)-(b.x-c.x)*(a.y-b.y); }

int    Set(int N,int pos){ return N=N | (1<<pos);}
int  Reset(int N,int pos){return N= N & ~(1<<pos);}
bool Check(int N,int pos){return (bool)(N & (1<<pos));}
template< class T, class X > inline T   togglebit(T a, X i) { T t=1;return (a^(t<<i)); }

double DEG(double x) { return (180.0*x)/(PI);}
double RAD(double x) { return (x*(double)PI)/(180.0);}

#define VI  vector< int >
#define VII vector< VI >
#define VLL vector< LL >
#define PII pair< int , int >
#define PLL pair< LL , LL >
#define VPI vector< PII >

///         0123456789
#define MX  100007
#define MOD 1000000007
#define INF (1<<30)-1+(1<<30)
#define eps 1e-9

#define base ((1<<l)-1)
#define lft (idx<<1)
#define rgt (lft|1)
#define mid ((l+r)>>1)

/// Hashing Bases & MOD
///           0123456789
#define Base1 10000019ULL
#define Base2 10000079ULL
#define Base3 10000103ULL
#define MOD1  1000000007ULL
#define MOD2  1000000009ULL
#define MOD3  1000000021ULL
#define LOGX  17
#define FCIN  ios_base::sync_with_stdio(0); cin.tie(0)

LL dis[1007];
bool vis[1007];
bool erase[10007];
VI adj[MX];
int val[MX];
pair< PII , int > edge[10007];

void Init(int n){
    for (int i=0;i<=n;i++){
        dis[i] = 1LL<<60;
        vis[i] = 0;
    }
}

void SPFA(int s,int n){
    queue<int> q;
    Init(n);

    q.PS(s);
    dis[s] = 0;
    vis[s] = 1;

    while(!q.empty()){
        int u = q.front();q.pop();

        vis[s] = 0;

        for (int i=0;i<adj[u].size();i+=2){
            int v = adj[u][i];
            int id = adj[u][i+1];
            int w = edge[id].Y;

            dis[v] = min(dis[v], dis[u]+w);

            if (!vis[v]){
                q.PS(v);
                vis[v] = 1;
            }
        }
    }
}

int main(){
    //cout << sizeof(dis)/1e6 << endl;
    //cout << sizeof(par)/1e6 << endl;
    //cout << sizeof(del)/1e6 << endl;
    //cout << sizeof(vis)/1e6 << endl;

    DII(n,m);
    DIII(l,s,t);

    for (int i=1;i<=m;i++){
        DIII(u,v,w);

        if (!w)
            erase[i] = 1, w = 1;

        adj[u].PB(v);
        adj[u].PB(i);

        adj[v].PB(u);
        adj[v].PB(i);

        edge[i] = MP( MP(u,v),w );
    }

    SPFA(s,n);

    if (dis[t] > l){
        puts("NO");
        return 0;
    }

    for (int u=0;u<n;u++){
        for (int i=0;i<adj[u].size();i+=2){
            int id = adj[u][i+1];
            //cout << id << "-> " << erase[id] << endl;
            if (!erase[id]) continue;

            SPFA(s,n);
            //cout << id << ": " << dis[t] << endl;
            if (dis[t] <= l)
                edge[id].Y += (l-dis[t]);
        }
    }

    SPFA(s,n);

    if (dis[t] != l){
        puts("NO");
        return 0;
    }

    puts("YES");

    for (int i=1;i<=m;i++)
        P("%d %d %d\n",edge[i].X.X, edge[i].X.Y, edge[i].Y);

return 0;
}
/*
5 2 13 0 4
0 1 5
2 1 0
*
4 5 10 1 2
0 1 3
1 2 0
1 3 4
2 3 4
2 0 6
*/


/*****************************************************************
 *                   BISMILLAHIR RAHMANIR RAHIM                  *
 *          Raihat Zaman Neloy                                   *
 *          JU-CSE-21                                            *
 *          raihatneloy                                          *
 *****************************************************************/

#include<bits/stdc++.h>

//#include<algorithm>
//#include<cstdio>
//#include<sstream>
//#include<cstdlib>
//#include<cctype>
//#include<cmath>
//#include<set>
//#include<queue>
//#include<stack>
//#include<list>
//#include<iostream>
//#include<fstream>
//#include<numeric>
//#include<string>
//#include<vector>
//#include<cstring>
//#include<map>
//#include<iterator>
//#include<deque>
//#include<climits>
//#include<complex>

#define S scanf
#define P printf

#define LL long long int
#define ULL unsigned long long int
#define D double

#define SQR(n)      (n*n)
#define PI          2.0*acos(0.0)

#define all(a) a.begin(),a.end()
#define X  first
#define Y  second
#define MP make_pair
#define NL P("\n")

#define open       freopen("input.txt","r",stdin)
#define close      freopen ("output.txt","w",stdout)
#define S1(a)      scanf("%d",&a)
#define S2(a,b)    scanf("%d%d",&a,&b)
#define S3(a,b,c)  scanf("%d%d%d",&a,&b,&c)
#define SL1(a)     scanf("%lld",&a)
#define SL2(a,b)   scanf("%lld%lld",&a,&b)
#define SL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define CHR        getchar()
#define PB(x)      push_back(x)
#define pb         push_back
#define PP         pop_back()
#define PF(x)      push_front(x)
#define PPF(x)     pop_front()
#define PS(x)      push(x)
#define sz()       size()
#define UB         upper_bound
#define LB         lower_bound
#define mxe(a,n)   (*max_element(a,a+n))
#define mne(a,n)   (*min_element(a,a+n))
#define SUM(a,n)   (accumulate(a,a+n,0))
#define countbit(x) __builtin_popcount(x)
#define DBG(n)      P("Done %d\n",n);

// I/O
#define I(X)                       scanf("%d", &(X))
#define II(X, Y)                   scanf("%d%d", &(X), &(Y))
#define III(X, Y, Z)               scanf("%d%d%d", &(X), &(Y), &(Z))
#define DI(X) int (X);             scanf("%d", &X)
#define DII(X, Y) int X, Y;        scanf("%d%d", &X, &Y)
#define DIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)

#define ILL(X)          scanf("%lld", &(X))
#define DILL(X) LL (X); scanf("%lld", &X)

// LOOP
#define repv(i,a) for(int i=0;i<(int)a.size();i++)
#define revv(i,a) for(int i=((int)a.size())-1;i>=0;i--)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rev(i,a,b) for(int i=a;i>=b;i--)

#define FS(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++)

#define MEM(a,val) memset(a,val,sizeof(a));
#define SET(a)     memset(a,-1,sizeof a)
#define CLR(a)     memset(a,0,sizeof a)
#define CMPL       cerr<< "Compilation Process Finished\n";cerr<< "----------------------------\n"

using namespace std;

template <typename T> T BigMod (T b,T p,T m){if (p == 0) return 1;if (p%2 == 0){T s = BigMod(b,p/2,m);return ((s%m)*(s%m))%m;}return ((b%m)*(BigMod(b,p-1,m)%m))%m;}
template <typename T> T ModInv (T b,T m){return BigMod(b,m-2,m);}
template <typename T> T in(){char ch;T n = 0;bool ng = false;while (1){ch = getchar();if (ch == '-'){ng = true;ch = getchar();break;}if (ch>='0' && ch<='9')     break;}while (1){n = n*10 + (ch - '0');ch = getchar();if (ch<'0' || ch>'9')   break;}return (ng?-n:n);}
template <typename T> T POW(T B,T P){ if(P==0) return 1; if(P&1) return B*POW(B,P-1);  else return SQR(POW(B,P/2));}
template <typename T> T Bigmod(T b,T p,T m){ if(p==0) return 1; else if (!(p&1)) return SQR(Bigmod(b,p/2,m)) % m;else return ((b % m) * Bigmod(b,p-1,m)) % m;}
template <typename T> T Dis(T x1,T y1,T x2, T y2){return sqrt( SQR(x1-x2) + SQR(y1-y2) );}
template <typename T> T Angle(T x1,T y1,T x2, T y2){ return atan( double(y1-y2) / double(x1-x2));}
template <typename T> T DIFF(T a,T b) { T d = a-b;if(d<0)return -d;else return d;}
template <typename T> T ABS(T a) {if(a<0)return -a;else return a;}
template <typename T> T gcd(T a,T b){if(a<0)return gcd(-a,b);if(b<0)return gcd(a,-b);return (b==0)?a:gcd(b,a%b);}
template <typename T> T lcm(T a,T b) {if(a<0)return lcm(-a,b);if(b<0)return lcm(a,-b);return a*(b/gcd(a,b));}
template <typename T> T euclide(T a,T b,T &x,T &y) {if(a<0){T d=euclide(-a,b,x,y);x=-x;return d;}   if(b<0){T d=euclide(a,-b,x,y);y=-y;return d;}   if(b==0){x=1;y=0;return a;}else{T d=euclide(b,a%b,x,y);T t=x;x=y;y=t-(a/b)*y;return d;}}
template <typename T> void ia (T a[],int n){for (int i=0; i<n; i++) cin >> a[i];}
template <typename T> void pa (T a[],int n){for (int i=0; i<n-1; i++) cout << a[i] << " ";cout << a[n-1] << endl;}
template <typename T> LL isLeft(T a,T b,T c) { return (a.x-b.x)*(b.y-c.y)-(b.x-c.x)*(a.y-b.y); }

int    Set(int N,int pos){ return N=N | (1<<pos);}
int  Reset(int N,int pos){return N= N & ~(1<<pos);}
bool Check(int N,int pos){return (bool)(N & (1<<pos));}
template< class T, class X > inline T   togglebit(T a, X i) { T t=1;return (a^(t<<i)); }

double DEG(double x) { return (180.0*x)/(PI);}
double RAD(double x) { return (x*(double)PI)/(180.0);}

#define VI  vector< int >
#define VII vector< VI >
#define VLL vector< LL >
#define PII pair< int , int >
#define PLL pair< LL , LL >
#define VPI vector< PII >

///         0123456789
#define MX  100007
#define MOD 1000000007
#define INF (1<<30)-1+(1<<30)
#define eps 1e-9

#define base ((1<<l)-1)
#define lft (idx<<1)
#define rgt (lft|1)
#define mid ((l+r)>>1)

/// Hashing Bases & MOD
///           0123456789
#define Base1 10000019ULL
#define Base2 10000079ULL
#define Base3 10000103ULL
#define MOD1  1000000007ULL
#define MOD2  1000000009ULL
#define MOD3  1000000021ULL
#define LOGX  17
#define FCIN  ios_base::sync_with_stdio(0); cin.tie(0)

LL dis[1007][10007];
short par[1007][10007];
short del[1007][10007];
bool vis[1007][10007];
VI adj[MX];
pair< PII , int > edge[10007];

void SPFA(int s){
    queue<int>q;

    q.PS(s);
    q.PS(0);

    vis[s][0] = 1;
    par[s][0] = -1;
    dis[s][0] = 0;

    while(!q.empty()){
        int u = q.front();q.pop();
        int x = q.front();q.pop();

        vis[u][x] = 0;

        for (int i=0;i<adj[u].size();i+=3){
            int v = adj[u][i];
            int w = adj[u][i+1];
            int id = adj[u][i+2];

            if (dis[v][x+(w==0)] > dis[u][x]+w){
                dis[v][x+(w==0)] = dis[u][x]+w;
                par[v][x+(w==0)] = u;
                del[v][x+(w==0)] = id;

                if (!vis[v][x+(w==0)]){
                    q.PS(v);
                    q.PS(x+(w==0));
                }
            }
        }
    }
}

void Init(int n,int m){
    for (int i=0;i<=n;i++){
        for (int j=0;j<=m;j++){
            dis[i][j] = 1LL<<60;
        }
    }
}

int main(){
    //cout << sizeof(dis)/1e6 << endl;
    //cout << sizeof(par)/1e6 << endl;
    //cout << sizeof(del)/1e6 << endl;
    //cout << sizeof(vis)/1e6 << endl;

    DII(n,m);
    DIII(l,s,t);

    Init(n,m);

    for (int i=1;i<=m;i++){
        DIII(u,v,w);

        adj[u].PB(v);
        adj[u].PB(w);
        adj[u].PB(i);

        adj[v].PB(u);
        adj[v].PB(w);
        adj[v].PB(i);

        edge[i] = MP( MP(u,v),w );
    }

    SPFA(s);

    if (dis[t][0] == l){
        LL lim = 1000000000000000000LL;

        puts("YES");
        for (int i=1;i<=n;i++){
            P("%d %d ",edge[i].X.X,edge[i].X.Y);

            if (edge[i].Y == 0) P("%lld\n",lim);
            else                P("%d\n",edge[i].Y);
        }

        return 0;
    }

    for (int i=1;i<=m;i++){
        //cout << dis[t][i] << endl;
        if (l - dis[t][i] < i)  continue;

        VI xx;

        int u = t, x = i;
        //cout << "Path:\n";
        while(par[u][x] != -1){
            //cout << u << ": " << x << endl;
            int id = del[u][x];
            //cout << id << endl;
            if (edge[id].Y == 0){
                //cout << "Dhuklo\n";
                xx.PB(id);
            }

            u = par[u][x];
            if (edge[id].Y == 0)
                x --;
        }
        //cout << "--------\n";

        int baki = l - dis[t][i];

        for (int j=0;j<xx.size();j++){
            //cout << "-> " << xx[j] << endl;
            edge[ xx[j] ].Y = 1;
            baki --;
        }

        edge[ xx.back() ].Y += baki;

        puts("YES");
        for (int j=1;j<=m;j++){
            P("%d %d %d\n",edge[j].X.X, edge[j].X.Y, edge[j].Y);
        }

        return 0;
    }

    puts("NO");
return 0;
}


/*****************************************************************
 *                   BISMILLAHIR RAHMANIR RAHIM                  *
 *          Raihat Zaman Neloy                                   *
 *          JU-CSE-21                                            *
 *          raihatneloy                                          *
 *****************************************************************/

#include<bits/stdc++.h>

//#include<algorithm>
//#include<cstdio>
//#include<sstream>
//#include<cstdlib>
//#include<cctype>
//#include<cmath>
//#include<set>
//#include<queue>
//#include<stack>
//#include<list>
//#include<iostream>
//#include<fstream>
//#include<numeric>
//#include<string>
//#include<vector>
//#include<cstring>
//#include<map>
//#include<iterator>
//#include<deque>
//#include<climits>
//#include<complex>

#define S scanf
#define P printf

#define LL long long int
#define ULL unsigned long long int
#define D double

#define SQR(n)      (n*n)
#define PI          2.0*acos(0.0)

#define all(a) a.begin(),a.end()
#define X  first
#define Y  second
#define MP make_pair
#define NL P("\n")

#define open       freopen("input.txt","r",stdin)
#define close      freopen ("output.txt","w",stdout)
#define S1(a)      scanf("%d",&a)
#define S2(a,b)    scanf("%d%d",&a,&b)
#define S3(a,b,c)  scanf("%d%d%d",&a,&b,&c)
#define SL1(a)     scanf("%lld",&a)
#define SL2(a,b)   scanf("%lld%lld",&a,&b)
#define SL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define CHR        getchar()
#define PB(x)      push_back(x)
#define pb         push_back
#define PP         pop_back()
#define PF(x)      push_front(x)
#define PPF(x)     pop_front()
#define PS(x)      push(x)
#define sz()       size()
#define UB         upper_bound
#define LB         lower_bound
#define mxe(a,n)   (*max_element(a,a+n))
#define mne(a,n)   (*min_element(a,a+n))
#define SUM(a,n)   (accumulate(a,a+n,0))
#define countbit(x) __builtin_popcount(x)
#define DBG(n)      P("Done %d\n",n);

// I/O
#define I(X)                       scanf("%d", &(X))
#define II(X, Y)                   scanf("%d%d", &(X), &(Y))
#define III(X, Y, Z)               scanf("%d%d%d", &(X), &(Y), &(Z))
#define DI(X) int (X);             scanf("%d", &X)
#define DII(X, Y) int X, Y;        scanf("%d%d", &X, &Y)
#define DIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)

#define ILL(X)          scanf("%lld", &(X))
#define DILL(X) LL (X); scanf("%lld", &X)

// LOOP
#define repv(i,a) for(int i=0;i<(int)a.size();i++)
#define revv(i,a) for(int i=((int)a.size())-1;i>=0;i--)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rev(i,a,b) for(int i=a;i>=b;i--)

#define FS(x) for(typeof (x.begin()) it = x.begin(); it != x.end (); it++)

#define MEM(a,val) memset(a,val,sizeof(a));
#define SET(a)     memset(a,-1,sizeof a)
#define CLR(a)     memset(a,0,sizeof a)
#define CMPL       cerr<< "Compilation Process Finished\n";cerr<< "----------------------------\n"

using namespace std;

template <typename T> T BigMod (T b,T p,T m){if (p == 0) return 1;if (p%2 == 0){T s = BigMod(b,p/2,m);return ((s%m)*(s%m))%m;}return ((b%m)*(BigMod(b,p-1,m)%m))%m;}
template <typename T> T ModInv (T b,T m){return BigMod(b,m-2,m);}
template <typename T> T in(){char ch;T n = 0;bool ng = false;while (1){ch = getchar();if (ch == '-'){ng = true;ch = getchar();break;}if (ch>='0' && ch<='9')     break;}while (1){n = n*10 + (ch - '0');ch = getchar();if (ch<'0' || ch>'9')   break;}return (ng?-n:n);}
template <typename T> T POW(T B,T P){ if(P==0) return 1; if(P&1) return B*POW(B,P-1);  else return SQR(POW(B,P/2));}
template <typename T> T Bigmod(T b,T p,T m){ if(p==0) return 1; else if (!(p&1)) return SQR(Bigmod(b,p/2,m)) % m;else return ((b % m) * Bigmod(b,p-1,m)) % m;}
template <typename T> T Dis(T x1,T y1,T x2, T y2){return sqrt( SQR(x1-x2) + SQR(y1-y2) );}
template <typename T> T Angle(T x1,T y1,T x2, T y2){ return atan( double(y1-y2) / double(x1-x2));}
template <typename T> T DIFF(T a,T b) { T d = a-b;if(d<0)return -d;else return d;}
template <typename T> T ABS(T a) {if(a<0)return -a;else return a;}
template <typename T> T gcd(T a,T b){if(a<0)return gcd(-a,b);if(b<0)return gcd(a,-b);return (b==0)?a:gcd(b,a%b);}
template <typename T> T lcm(T a,T b) {if(a<0)return lcm(-a,b);if(b<0)return lcm(a,-b);return a*(b/gcd(a,b));}
template <typename T> T euclide(T a,T b,T &x,T &y) {if(a<0){T d=euclide(-a,b,x,y);x=-x;return d;}   if(b<0){T d=euclide(a,-b,x,y);y=-y;return d;}   if(b==0){x=1;y=0;return a;}else{T d=euclide(b,a%b,x,y);T t=x;x=y;y=t-(a/b)*y;return d;}}
template <typename T> void ia (T a[],int n){for (int i=0; i<n; i++) cin >> a[i];}
template <typename T> void pa (T a[],int n){for (int i=0; i<n-1; i++) cout << a[i] << " ";cout << a[n-1] << endl;}
template <typename T> LL isLeft(T a,T b,T c) { return (a.x-b.x)*(b.y-c.y)-(b.x-c.x)*(a.y-b.y); }

int    Set(int N,int pos){ return N=N | (1<<pos);}
int  Reset(int N,int pos){return N= N & ~(1<<pos);}
bool Check(int N,int pos){return (bool)(N & (1<<pos));}
template< class T, class X > inline T   togglebit(T a, X i) { T t=1;return (a^(t<<i)); }

double DEG(double x) { return (180.0*x)/(PI);}
double RAD(double x) { return (x*(double)PI)/(180.0);}

#define VI  vector< int >
#define VII vector< VI >
#define VLL vector< LL >
#define PII pair< int , int >
#define PLL pair< LL , LL >
#define VPI vector< PII >

///         0123456789
#define MX  100007
#define MOD 1000000007
#define INF (1<<30)-1+(1<<30)
#define eps 1e-9

#define base ((1<<l)-1)
#define lft (idx<<1)
#define rgt (lft|1)
#define mid ((l+r)>>1)

/// Hashing Bases & MOD
///           0123456789
#define Base1 10000019ULL
#define Base2 10000079ULL
#define Base3 10000103ULL
#define MOD1  1000000007ULL
#define MOD2  1000000009ULL
#define MOD3  1000000021ULL
#define LOGX  17
#define FCIN  ios_base::sync_with_stdio(0); cin.tie(0)

LL dis[1007];
bool vis[1007];
bool erase[10007];
VI adj[MX];
int val[MX];
pair< PII , int > edge[10007];

void Init(int n){
    for (int i=0;i<=n;i++){
        dis[i] = 1LL<<60;
        vis[i] = 0;
    }
}

void SPFA(int s,int n){
    queue<int> q;
    Init(n);

    q.PS(s);
    dis[s] = 0;
    vis[s] = 1;

    while(!q.empty()){
        int u = q.front();q.pop();

        vis[s] = 0;

        for (int i=0;i<adj[u].size();i+=2){
            int v = adj[u][i];
            int id = adj[u][i+1];
            int w = edge[id].Y;

            dis[v] = min(dis[v], dis[u]+w);

            if (!vis[v]){
                q.PS(v);
                vis[v] = 1;
            }
        }
    }
}

int main(){
    //cout << sizeof(dis)/1e6 << endl;
    //cout << sizeof(par)/1e6 << endl;
    //cout << sizeof(del)/1e6 << endl;
    //cout << sizeof(vis)/1e6 << endl;

    DII(n,m);
    DIII(l,s,t);

    for (int i=1;i<=m;i++){
        DIII(u,v,w);

        if (!w)
            erase[i] = 1;

        adj[u].PB(v);
        adj[u].PB(i);

        adj[v].PB(u);
        adj[v].PB(i);

        edge[i] = MP( MP(u,v),w );
    }

    for (int i=1;i<=m;i++){
        if (erase[i])
            edge[i].Y = 1;
    }

    SPFA(s,n);
    LL best = dis[t];

    for (int i=1;i<=m;i++)
        if (erase[i])
            edge[i].Y = 2e9;

    SPFA(s,n);
    LL worst = dis[t];

    if (l < best || worst < l){
        puts("NO");
        return 0;
    }

    if (worst > l)
        for (int i=1;i<=m;i++){
            if (!erase[i])  continue;

            edge[i].Y = 1;
            SPFA(s,n);

            if (dis[t] <= l){
                edge[i].Y += (l-dis[t]);
                break;
            }
        }

    SPFA(s,n);

    if (dis[t] != l){
        puts("NO");
        return 0;
    }

    puts("YES");

    for (int i=1;i<=m;i++)
        P("%d %d %d\n",edge[i].X.X, edge[i].X.Y, edge[i].Y);

return 0;
}