先判断无解情况:
情况1:不加'0'边时 最短路d[t]<L 加入'0'边不会使最短路d[t]增大 则d[t]不可能达到L
情况2:加入'0'边时,使'0'边的权为最小的1 此时最小d[t]>L 无解
剩下的情况都为有解 因为(s,t)的路径路径只剩下 d[t]<L&&d[t]中有'0'边
不断对最短路径中的'0'边进行松弛使之达到L 此时判断最短路是等于L(松弛后的次短路变为最短路可能小于L)
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
#define fi first
#define se second
#define pb push_back
typedef pair<ll,ll> ii;//距离和目标点
const int M =1e5+20;
const int N=1001;
const ll inf=(ll)1e18;
int n,m,l,s,t;
int L[M],R[M];//边集l[i],r[i])
ll d1[N];//去掉权值为0的边的最短路
ll d2[N];
ll dist[N][N];//
vector<ii> adj[N];//u,v,w
vector<int> adj2[N];
void dijkstra()
{
priority_queue<ii,vector<ii>,greater<ii> > q;
d1[s]=0;
q.push(ii(0,s));
while(!q.empty())
{
int u=q.top().se;//当前最小的d[i]出列 (路径递增)
ll d=q.top().fi;
q.pop();
for(int i=0;i<adj[u].size();i++)
{
int v=adj[u][i].fi;//
ll w=adj[u][i].se;
if(d1[v]>d+w)
{
d1[v]=d+w;
q.push(ii(d1[v],v));
}
}
}
}
int par[N];
bool dijkstra2()
{
d2[s]=0;
priority_queue<ii,vector<ii>,greater<ii> > q;
q.push(ii(0,s));
while(!q.empty())
{
int u=q.top().se;
ll d=q.top().fi;
q.pop();
for(int i=0;i<adj2[u].size();i++)
{
int v=adj2[u][i];
ll w=dist[u][v];//
if(d2[v]>d+abs(w))
{
d2[v]=d+abs(w);//边权值至少为1
par[v]=u;
q.push(ii(d2[v],v));
}
}
}
//以上是 加上被Erase的边时的最短路d2[]
if(d2[t]>l)
return false;
int cur=t;
//此时最短路小于等于L && 路径中一定包含0,不断调整'0'边使得最短路为L即可
while(cur!=s)
{
int p=par[cur];
if(dist[p][cur]<0)
{
dist[p][cur]=dist[cur][p]=-2;
}
cur=par[cur];
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
if(dist[i][j] == -1) //小优化 (s,t)<L && 包含'0'边的次短路径可能很多 去除不与最短路径相交的次短路径
//只需要保留最短路径上的'0'边 使得relax操作最多进行n次
{
dist[i][j] = inf;
}
}
}
cur = t;
while(cur != s)
{
int p = par[cur];
if(dist[p][cur] < 0)
{
dist[p][cur] = -1; dist[cur][p] = -1;
}
cur = par[cur];
}
return true;
}
void print()
{
cout << "YES\n";
for(int i = 0; i < m; i++)
{
int u = L[i]; int v = R[i];
ll d = dist[u][v];
if(d < 0) d = -d;
cout << u << ' ' << v << ' ' << d << '\n';
}
}
bool relax()
{
for(int i=0;i<n;i++) d2[i]=inf;
d2[s]=0;
priority_queue<ii, vector<ii> ,greater<ii> > q;
q.push(ii(0,s));
while(!q.empty())
{
int u=q.top().se;
ll d=q.top().fi;
q.pop();
for(int i=0;i<adj2[u].size();i++)
{
int v=adj2[u][i];
ll w=dist[u][v];
if(d+abs(w)<d2[v])
{
d2[v]=d+abs(w);
par[v]=u;
q.push(ii(d2[v],v));
}
}
}
if(d2[t]==l) return true;
int cur=t;
bool meet =false;
while(cur!=s)//使该路径=L
{
int p=par[cur];
if(!meet&& dist[p][cur]<0)
{
ll d=abs(dist[p][cur]);
dist[cur][p]=dist[p][cur]=d+l-d2[t];
meet=true;
}
cur=par[cur];
if(meet)
break;
}
return false;//松弛后最短路可能<L 继续松弛使得最短路为L
}
int dist1[N][N];
int main()
{
cin>>n>>m>>l>>s>>t;
memset(dist1, -1, sizeof(dist1));
for(int i=0;i<m;i++)
{
long long u,v,w;
scanf("%lld%lld%lld",&u,&v,&w);
if(w>0)
{
adj[u].pb(ii(v,w));
adj[v].pb(ii(u,w));//双向边,不包含0
adj2[u].pb(v);//无权边
adj2[v].pb(u);
dist1[u][v]=w; dist1[v][u]=w;//打印时用
dist[u][v]=w; dist[v][u]=w;
}
else
{
adj2[u].pb(v);//无权边 包含0
adj2[v].pb(u);
dist[u][v]=-1; dist[v][u]=-1;
}
L[i]=u; R[i]=v;
}
for(int i=0;i<n;i++)
{
d1[i]=inf;
d2[i]=inf;
}
dijkstra();//求去掉权值为0的边的最短路
if(d1[t]<l)//去掉权值为0的边的最短路<l 则加上去掉的边(正的) 最短路还是d1[t] 所以最短路不可能达到l
{
cout<<"NO"<<endl;
return 0;
}
if(d1[t]==l)
{
cout<<"YES"<<endl;
for(int i=0;i<m;i++)
{
int u=L[i];
int v=R[i];
ll d=dist1[u][v];
if(d<=0) d=inf;//使得最短路不可能变小
printf("%d %d %lld\n",u,v,d);
}
return 0;
}
//以上是去掉'0'边是的情况 d1[t]<l则不
bool tmp=dijkstra2();
if(!tmp)
{
cout<<"NO"<<endl;
return 0;
}
//那么如果此时最短路小于L,不断调整最短路中'0'边使得最短路为L即可
while(!relax())//最多松弛n次
{
relax();
}
print();
return 0;
}