给n点m边,L,s,t
修改m条边中边为0的边,
使满足s,t的最短路长度是L,且输出答案的时候边为0的边的权值必须在[1,1e18]内
做法,1.先做一次假设每条零边都不可经过的最短路,如果dis[t] < L,则是NO
2.再将每条零边修改成1,如果此时dis[t] > L 也是 NO
除了这两种情况,就必有YES,至于为啥,按下面的思路想一下就知道了
3.将第二个操作后的最短路拿出来,对非最短路上的零边都赋值 1e18,
遍历这条最短路上的所有零边
如果dis[t] < L
那这条零边增加一个值使这条最短路等于L
然后再求最短路,(注意此时的最短路可能变成另一条路了,但是仍经过其余未赋值过的零边)
如果此时的dis[t] 仍然 < L
再对这条边增加一个值,直到遍历完这个最短路上的零边集合,一定会有解
因为每改变一条边dis[t]仍小于L,说明新的最短路肯定经过至少一条未改变过的零边
那么不断改变其它零边,如果改变的这条零边不属于新的最短路路径内的边,那么dis[t]依旧不变,最短路也不变,直到找到属于最短路路径内的边,然后修改了这条边之后也许又会回到上面的情况,但是在修改到最后一条零边的时候只会有三种情况:
1.dis[t] > L,这种情况显然不会出现
2.dis[t] == L
3.dis[t] < L ,假设在修改完上一条零边的时候,得到的结果dis[K-1][t] < L,
那么最后一条零边是肯定在新的最短路内的,那么修改完这个dis[K][t]==L,所以是不会出现dis[t] < L的情况的
dis[K][t],是为了好理解,就是修改了前K条零边后所得到的最短路。。实际上还是dis[t]
复杂度是nmlog n
时间是4S,108ms可过
#include
using namespace std;
typedef long long LL;
const int maxn = 10000+5;
const LL INF = 1e18;
int n,m,s,t;
LL L;
struct uv {
int u,v;
LL w;
} edg[maxn],tp[maxn];
struct qnode {
int v;
LL w;
qnode(int _v=0,LL _w=0):v(_v),w(_w) {}
bool operator <(const qnode &r) const {
return w > r.w;
}
};
struct Edge {
int v;
LL w;
Edge(int _v=0,int _w=0):v(_v),w(_w) {}
};
vector E[maxn];
LL dis[maxn];
bool vis[maxn],p[1002][1002];
int pre[maxn];
LL EG[1002][1002];
void dijkstra() {
memset(vis,0,sizeof vis);
memset(pre,0,sizeof pre);
for(int i=0; ique;
while(!que.empty()) que.pop();
dis[s] = 0;
que.push(qnode(s,0));
qnode tmp;
while(!que.empty()) {
tmp = que.top();
que.pop();
int u = tmp.v;
if(vis[u]) continue;
vis[u] = true;
for(int i=0; iint v = E[u][i].v;
LL w = E[u][i].w;
if(!vis[v]&&dis[v]>dis[u]+w) {
dis[v] = dis[u] + w;
// cout<
que.push(qnode(v,dis[v]));
pre[v] = u;
}
}
}
}
int main() {
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
cin>>n>>m>>L>>s>>t;
bool fs = 0,ft = 0;
int cnt = 0;
for(int i=0; iint u,v;
LL w;
cin>>u>>v>>w;
if(s==u||s==v) fs = 1;
if(t==u||t==v) ft = 1;
edg[i].u = u;
edg[i].v = v;
edg[i].w = w;
if(w) {
E[u].push_back(Edge(v,w));
E[v].push_back(Edge(u,w));
} else p[u][v] = p[v][u] = 1,cnt++;
}
if(!fs||!ft) {
puts("NO");
return 0;
}
dijkstra();
//for(int i=0; i
//printf("%I64d%c",dis[i],i==n-1?'\n':' ');
if(dis[t] < L) {
puts("NO");
return 0;
}
for(int i=0; iint u,v;
LL w;
u = edg[i].u;
v = edg[i].v;
w = edg[i].w;
if(!w) {
E[u].push_back(Edge(v,1));
E[v].push_back(Edge(u,1));
}
}
dijkstra();
//for(int i=0; i
// printf("%I64d%c",dis[i],i==n-1?'\n':' ');
if(L - dis[t]<0) {
puts("NO");
return 0;
}
int k = pre[t],e = t,totedge = 0;
while(1) {
if(p[k][e]) {
tp[totedge].u = k;
tp[totedge].v = e;
totedge++;
p[k][e] = p[e][k] = 0;
EG[k][e] = EG[e][k] = 1;
}
if(k == s) break;
e = k;
k = pre[k];
}
for(int i=0; iint u,v;
LL w;
u = edg[i].u;
v = edg[i].v;
if(p[u][v]) {
//cout<
for(int k=0; kif (E[u][k].v == v) {
E[u][k].w = INF;
break;
}
}
for(int k=0; kif(E[v][k].v == u) {
E[v][k].w = INF;
break;
}
}
}
}
dijkstra();
LL dist = dis[t];
puts("YES");
for(int i=0; iint u = tp[i].u, v = tp[i].v;
for(int k=0; kif(E[u][k].v == v) {
E[u][k].w = 1 + L - dis[t];
break;
}
}
for(int k=0; kif(E[v][k].v == u) {
E[v][k].w = 1 + L - dis[t];
break;
}
}
dijkstra();
EG[u][v] = EG[v][u] = 1 + L - dist;
dist = dis[t];
if(dis[t] == L) break;
}
if(dis[t] == L) {
for(int i=0; iint u = edg[i].u,v = edg[i].v;
LL w = edg[i].w;
//cout<
if(w)
printf("%d %d %I64d\n",u,v,w);
else if(p[u][v])
printf("%d %d %I64d\n",u,v,INF);
else printf("%d %d %I64d\n",u,v,EG[u][v]);
}
return 0;
}
return 0;
}