題解:
題意大致爲給定的無向圖,且給定起點和終點,以及部分知道長度的邊,讓你補全不知道長度的邊使得從到的最短路爲
解題可以分爲3個步驟
- 不將不知道長度的邊跳過,求最短路,若最短路小於L則一定不可能成功輸出NO,若等於則將未知邊長設定爲INF若大於則執行2
- 將所有未知邊都設成1,跑最短路,若最短路大於L則一定不能成功(因爲題意規定邊長最小爲1)輸出NO,否則執行第3步
- 首先在第二步中回溯一遍最短路,將經過的未知邊打上標記。對於未打上標記的未知邊設值爲INF,其他值爲1,然後依次枚舉這些點二分這些點的答案,跑最短路。(每次確定一點答案後再跑一遍最短路,若最短路爲L則推出枚舉)
代碼:
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
//#include <random>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define PB push_back
#define MP make_pair
#define INF 1073741824
#define inf 1000000000000000000
#define pi 3.14159265358979323846
//#pragma comment(linker,"/STACK:10240000,10240000")
//mt19937 rand_(time(0));
const int N=3e5+7,M=2e6;
const long long mod=1e9+7;
inline int read(){int ret=0;char ch=getchar();bool f=1;for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');for(;isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;return f?ret:-ret;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}//逆元
ll wei[M];
int head[N],NEXT[M],ver[M],tot;void link(int u,int v,ll w){ver[++tot]=v;NEXT[tot]=head[u];head[u]=tot;wei[tot]=w;}
ll dis[N];
bool vis[N],mark[N],flag[N];
int que[N],pre[N];
int s,t;
int n;
ll L;
bool dij(int x){
for(int i=1;i<=n;i++){
dis[i]=inf;
vis[i]=false;
}
dis[x]=0;
priority_queue<pair<ll,int> >q;
q.push(MP(0,x));
while(!q.empty()){
x=q.top().second;
q.pop();
if(vis[x]) continue;
vis[x]=true;
for(int i=head[x];i;i=NEXT[i]){
int y=ver[i];
if(mark[i/2]) continue;
if(dis[y]>dis[x]+wei[i]){
dis[y]=dis[x]+wei[i];
q.push(MP(-dis[y],y));
}
}
}
if(dis[t]<L) return false;
else true;
}
bool DIJ(int x){
for(int i=1;i<=n;i++){
dis[i]=inf;
vis[i]=false;
}
dis[x]=0;
priority_queue<pair<ll,int> >q;
q.push(MP(0,x));
while(!q.empty()){
x=q.top().second;
q.pop();
if(vis[x]) continue;
vis[x]=true;
for(int i=head[x];i;i=NEXT[i]){
int y=ver[i];
//cout<<mark[i/2]<<' '<<y<<' '<<x<<endl;
if(dis[y]>dis[x]+(mark[i/2]?1LL:wei[i])){
dis[y]=dis[x]+(mark[i/2]?1LL:wei[i]);
q.push(MP(-dis[y],y));
pre[y]=i;
//cout<<y<<' '<<x<<endl;
}
}
}
// for(int i=1;i<=n;i++) cout<<dis[i]<<' ';
// cout<<endl;
//cout<<dis[t]<<endl;
if(dis[t]>L) return false;
else true;
}
void dijs(int x){
for(int i=1;i<=n;i++){
dis[i]=inf;
vis[i]=false;
}
dis[x]=0;
priority_queue<pair<ll,int> >q;
q.push(MP(0,x));
while(!q.empty()){
x=q.top().second;
q.pop();
if(vis[x]) continue;
vis[x]=true;
for(int i=head[x];i;i=NEXT[i]){
int y=ver[i];
if(dis[y]>dis[x]+wei[i]){
dis[y]=dis[x]+wei[i];
q.push(MP(-dis[y],y));
}
}
}
}
int main(){
//freopen("1.txt","r",stdin);
//ios::sync_with_stdio(false);
int m;
int u,v;
ll w;
tot=1;
scanf("%d%d%d%d%d",&n,&m,&L,&s,&t);
s++,t++;
for(int i=1;i<=m;i++){
scanf("%d%d%lld",&u,&v,&w);
link(u+1,v+1,w);
link(v+1,u+1,w);
if(w==0) mark[i]=true;
}
if(dij(s)){
if(dis[t]==L){
puts("YES");
for(int i=1;i<=m;i++){
if(mark[i])
printf("%d %d %lld\n",ver[i*2+1]-1,ver[i*2]-1,inf);
else
printf("%d %d %lld\n",ver[i*2+1]-1,ver[i*2]-1,wei[i*2]);
}
return 0;
}
if(DIJ(s)){
int tmp=t;
int ant=0;
while(tmp!=s){
if(mark[pre[tmp]/2]){
que[++ant]=pre[tmp]/2;
flag[pre[tmp]/2]=true;
}
tmp=ver[pre[tmp]^1];
}
for(int i=1;i<=m;i++){
if(mark[i]){
if(flag[i]){
wei[i*2]=wei[i*2+1]=1LL;
}
else {
wei[i*2]=wei[i*2+1]=inf;
}
}
}
for(int i=1;i<=ant;i++){
ll l=1,r=inf;
while(l<=r){
ll mi=(l+r)/2LL;
wei[que[i]*2]=wei[que[i]*2+1]=mi;
dijs(s);
if(dis[t]>L) r=mi-1;
else l=mi+1;
}
wei[que[i]*2]=wei[que[i]*2+1]=r;
dijs(s);
if(dis[t]==L) break;
}
puts("YES");
for(int i=1;i<=m;i++){
if(mark[i])
printf("%d %d %lld\n",ver[i*2+1]-1,ver[i*2]-1,wei[i*2]);
else
printf("%d %d %lld\n",ver[i*2+1]-1,ver[i*2]-1,wei[i*2]);
}
}
else puts("NO");
}
else puts("NO");
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}