思路當天沒想出來,結果晚上回去的路上,突然就想到了多次找最短路,補全L後,修改其他邊爲1e18。直到找到最短路爲L爲止。 用這個思路,代碼一遍就過了。終於A掉了,美滋滋!!
代碼:(因本人代碼水平有限,寫的挺長,代碼用時:2000ms)
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
#include<map>
#include<algorithm>
#define inf 0x3f3f3f3f
#include <algorithm>
#define N 10005
#define LL long long
#define mem(a,b) memset(a,b,sizeof(a));
using namespace std;
LL ansu[N],ansv[N];
LL answ[N];//存邊的信息
struct node
{
LL u,v,nex,id;
LL w,flag;
} e[400500];
LL head[N],f[N],vis[N];
LL cnt,S,T,n,m;
LL dis[N],L;
void add(LL u,LL v,LL w,LL id)
{
e[cnt].id=id;//哪條邊
e[cnt].u=u;
e[cnt].v=v;
e[cnt].w=w;
if(w==0) e[cnt].flag=0;//標記,邊長爲0,標記爲0
else e[cnt].flag=1;
e[cnt].nex=head[u];
head[u]=cnt++;
}
void init()
{
mem(head,-1);
cnt=0;
}
queue<LL>q;
map<LL,LL>ma;
void spfa(LL flag)
{
mem(f,-1);
mem(vis,0);
memset(dis,0x3f,sizeof dis);//初始化
dis[S]=0LL;//dis[i]表示i到出發點S的最短距離
vis[S]=1;//標記是否已經加入隊列
while(!q.empty())
q.pop();
q.push(S);
while(!q.empty())
{
LL u=q.front();
q.pop();
for(LL i=head[u]; ~i; i=e[i].nex)
{
LL v=e[i].v;
LL w=e[i].w;
if(flag&&!w) continue;//flag爲1的話,算最短路不帶邊長爲0的邊
if(dis[v]<=dis[u]+w) continue;
dis[v]=dis[u]+w;//更新v到S的最短距離
if(!flag) f[v]=i;//更新dis[v]後,更新f[v],f[v]存u到v的這條路的編號i,通過這個來找到最短路路徑。
if(vis[v]) continue;
vis[v]=1;
q.push(v);
}
vis[u]=0;
}
}
int main()
{
init();
scanf("%lld%lld%lld%lld%lld",&n,&m,&L,&S,&T);
for(LL i=0; i<m; i++)
{
scanf("%lld%lld%lld",&ansu[i],&ansv[i],&answ[i]);
add(ansu[i],ansv[i],answ[i],i);
add(ansv[i],ansu[i],answ[i],i);
}
spfa(1);
if(dis[T]<L)//計算出最短路(不帶0的邊),若太小,改變邊長爲0的邊,也無法改變這條最短路的值。
{
printf("NO\n");
return 0;
}
else if(dis[T]==L)//找到答案
{
printf("YES\n");
for(LL i=0; i<m; i++)
printf("%lld %lld %lld\n",ansu[i],ansv[i],answ[i]==0LL?L+10:answ[i]);
return 0;
}
for(int i=0;i<cnt;i++)//讓所有的邊長爲0的邊變成1(正整數)中的最小值
if(!e[i].flag)
answ[e[i].id]=e[i].w=1;
while(1)
{
spfa(0);//求出最短路
if(dis[T]>L)
{
printf("NO\n");//第一次求出此值,這是整個圖的最短路,因爲邊長爲零的邊一定至少是1,第一次就沒有大於L,那麼以後也不可能再大於L。
return 0;
}
else if(dis[T]==L)
{
printf("YES\n");
for(LL i=0; i<m; i++)
printf("%lld %lld %lld\n",ansu[i],ansv[i],answ[i]);
return 0;
}
else
{
LL u=T;
ma.clear();
LL sum=L-dis[T];
while(u!=S)
{
if(!e[f[u]].flag)
{
answ[e[f[u]].id]=e[f[u]].w=e[f[u]].w+sum;//將sum(差值)添加到第一個可修改邊上。
sum=0;
ma[e[f[u]].id]=1;//標記此最短路上可修改的邊的id
}
u=e[f[u]].u;//f[u]爲找到上一個節點的編號。
}
for(int i=0;i<cnt;i++)//此條最短路以外的所有可修改的邊全部修改成1e18,
if(!e[i].flag&&!ma[e[i].id])
answ[e[i].id]=e[i].w=L+10;
}
}
}