我的思路大概是先跑一遍最短路(不考虑所有0的边),如果比L还小自然不行。 然后第二次最短路将每个0的边当作1考虑,如果能到达并且小于等于L的话必然可以,同时记录下来最短路径(方便后续更新边上的值),更新完值之后剩下的还为0的边全部赋一个比L大的值就可以了
代码里一些不太好的习惯别太在意
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
struct edge {
int from;
int to;
int val;
int next;
};
const int maxn = 1005;
const int maxm = 2e5 + 10;
edge E[maxm];
int last[maxn];
int id = 0;
int n,m,L,s,t;
int dis[maxn];
int erased[maxn];
int arrive[maxn];
queue<int> Q;
void build(int st, int ed, int val) {
id ++;
E[id].from = st;
E[id].to = ed;
E[id].val = val;
E[id].next = last[st];
last[st] = id;
}
int main() {
cin >> n >> m >> L >> s >> t;
for(int i = 1;i <= m;i++)
{
int x,y,z;
cin >> x >> y >> z;
build(x,y,z);
build(y,x,z);
}
memset(dis,-1,sizeof(dis));
dis[s] = 0;
Q.push(s);
while(!Q.empty()) {
int pos = Q.front();
Q.pop();
for(int i = last[pos];i != 0;i = E[i].next) {
if(E[i].val != 0) {
if(dis[E[i].to] == -1 || dis[E[i].to] > dis[pos] + E[i].val) {
dis[E[i].to] = dis[pos] + E[i].val;
Q.push(E[i].to);
}
}
}
}
int temp = dis[t];
if(temp != -1 && temp < L)
{
cout << "NO" << endl;
return 0;
}
memset(dis,-1,sizeof(dis));
memset(erased,0,sizeof(erased));
memset(arrive,0,sizeof(arrive));
Q.push(s);
dis[s] = 0;
while(!Q.empty()) {
int pos = Q.front();
Q.pop();
for(int i = last[pos];i != 0;i = E[i].next) {
if(E[i].val == 0) {
if(dis[E[i].to] == -1 || dis[E[i].to] + erased[E[i].to] > dis[pos] + erased[pos] + 1)
{
dis[E[i].to] = dis[pos];
erased[E[i].to] = erased[pos] + 1;
arrive[E[i].to] = i;
Q.push(E[i].to);
}
}
else {
if(dis[E[i].to] == -1 || dis[E[i].to] + erased[E[i].to] > dis[pos] + erased[pos] + E[i].val)
{
dis[E[i].to] = dis[pos] + E[i].val;
erased[E[i].to] = erased[pos];
arrive[E[i].to] = i;
Q.push(E[i].to);
}
}
}
}
if(dis[t] == -1 || dis[t] + erased[t] > L) {
cout <<"NO"<<endl;
return 0;
}
bool up = false;
int pos = t;
int prev;
bool pd[maxn];
memset(pd,false,sizeof(pd));
while(pos != s) {
prev = E[arrive[pos]].from;
if(E[arrive[pos]].val == 0) {
if(up) {
E[arrive[pos]].val = 1;
if(arrive[pos] % 2 == 0)
E[arrive[pos] - 1].val = 1;
}
if(!up) {
E[arrive[pos]].val = L - dis[t] - erased[t] + 1;
if(arrive[pos] % 2 == 0)
E[arrive[pos] - 1].val = L - dis[t] - erased[t] + 1;
up = true;
}
}
if(pd[pos] == true)
cout <<"A "<< pos << endl;
pd[pos] = true;
pos = prev;
}
cout <<"YES"<<endl;
for(int i = 1;i <= id;i += 2)
{
if(E[i].val == 0)
E[i].val = L + 1;
cout << E[i].from << " " << E[i].to << " " << E[i].val <<endl;
}
return 0;
}
我大概测试了一下,tle的原因是因为在while里面,沿着最优路径一路往回寻找的时候形成了一个循环,然后我看半天代码没觉出任何出现循环的可能。