Codeforces 716D Complete The Graph(最短路+思维)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/GYH0730/article/details/82935981

D. Complete The Graph

time limit per test

4 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

ZS the Coder has drawn an undirected graph of n vertices numbered from 0 to n - 1 and m edges between them. Each edge of the graph is weighted, each weight is a positive integer.

The next day, ZS the Coder realized that some of the weights were erased! So he wants to reassign positive integer weight to each of the edges which weights were erased, so that the length of the shortest path between vertices s and t in the resulting graph is exactly L. Can you help him?

Input

The first line contains five integers n, m, L, s, t (2 ≤ n ≤ 1000,  1 ≤ m ≤ 10 000,  1 ≤ L ≤ 109,  0 ≤ s, t ≤ n - 1,  s ≠ t) — the number of vertices, number of edges, the desired length of shortest path, starting vertex and ending vertex respectively.

Then, m lines describing the edges of the graph follow. i-th of them contains three integers, ui, vi, wi(0 ≤ ui, vi ≤ n - 1,  ui ≠ vi,  0 ≤ wi ≤ 109). ui and vi denote the endpoints of the edge and wi denotes its weight. If wi is equal to 0then the weight of the corresponding edge was erased.

It is guaranteed that there is at most one edge between any pair of vertices.

Output

Print "NO" (without quotes) in the only line if it's not possible to assign the weights in a required way.

Otherwise, print "YES" in the first line. Next m lines should contain the edges of the resulting graph, with weights assigned to edges which weights were erased. i-th of them should contain three integers uivi and wi, denoting an edge between vertices ui and vi of weight wi. The edges of the new graph must coincide with the ones in the graph from the input. The weights that were not erased must remain unchanged whereas the new weights can be any positive integer not exceeding 1018.

The order of the edges in the output doesn't matter. The length of the shortest path between s and t must be equal to L.

If there are multiple solutions, print any of them.

Examples

input

5 5 13 0 4
0 1 5
2 1 2
3 2 3
1 4 0
4 3 4

output

YES
0 1 5
2 1 2
3 2 3
1 4 8
4 3 4

input

2 1 123456789 0 1
0 1 0

output

YES
0 1 123456789

input

2 1 999999999 1 0
0 1 1000000000

output

NO

Note

Here's how the graph in the first sample case looks like :

In the first sample case, there is only one missing edge weight. Placing the weight of 8 gives a shortest path from 0 to 4 of length 13.

In the second sample case, there is only a single edge. Clearly, the only way is to replace the missing weight with 123456789.

In the last sample case, there is no weights to assign but the length of the shortest path doesn't match the required value, so the answer is "NO".

题意:给出n个点,m条边,其中一些边的边权为0,要求把这些0边的边权都变为正边权后,使得s到t的最短路为L,并输出所有的边

思路:首先,记录所有0边权的边,在不加这些0边权的情况下跑一遍最短路

如果dis[t]比L小的话,直接输出NO,因为在我们加边后,最短路只能减小,不能增大

如果dis[t]等于L,输出YES,把所有0边的边权改为INF

如果dis[t]大于L,说明我们可以通过加之前记录的边权为0的边来减小最短路,添加的时候设边权为1,每添加一次就跑一遍最短路,如果在添加一条边后最短路<=L,那么这条边的权值再加上L-dis[t]后最短路就等于L了,剩下的0边权值设为INF,如果所有的0边改为1都加入后,最短路仍大于L,输出NO

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1005;
const int MAXM = 100005;
const ll INF = 1e17;
int tot,head[MAXN];
void init()
{
    tot = 0;
    memset(head,-1,sizeof(head));
}
struct Edge
{
    int from,to,next;
    ll w;
}edge[MAXM],e[MAXM];
void addedge(int u,int v,ll w)
{
    edge[tot].from = u;
    edge[tot].to = v;
    edge[tot].w = w;
    edge[tot].next = head[u];
    head[u] = tot++;
}
ll dis[MAXN];
bool vis[MAXN];
int n;
void spfa(int s)
{
    int u,v;
    for(int i = 0; i <= n; i++) {
        dis[i] = INF;
        vis[i] = false;
    }
    dis[s] = 0;
    queue<int> q;
    q.push(s);
    vis[s] = true;
    while(!q.empty()) {
        u = q.front();
        q.pop();
        vis[u] = false;
        for(int i = head[u]; i != -1; i = edge[i].next) {
            v = edge[i].to;
            if(dis[v] > dis[u] + edge[i].w) {
                dis[v] = dis[u] + edge[i].w;
                if(!vis[v]) {
                    q.push(v);
                    vis[v] = true;
                }
            }
        }
    }
}
int main(void)
{
    int m,l,s,t,u,v,cnt;
    ll w;
    while(scanf("%d %d %d %d %d",&n,&m,&l,&s,&t) != EOF) {
        init();
        cnt = 0;
        for(int i = 1; i <= m; i++) {
            scanf("%d %d %I64d",&u,&v,&w);
            if(w) {
                addedge(u,v,w);
                addedge(v,u,w);
            }
            else {
                e[cnt].from = u;
                e[cnt++].to = v;
            }
        }
        spfa(s);
        if(dis[t] < l) {
            printf("NO\n");
        }
        else if(dis[t] == l) {
            printf("YES\n");
            for(int i = 0; i < tot; i += 2) {
                printf("%d %d %I64d\n",edge[i].from,edge[i].to,edge[i].w);
            }
            for(int i = 0; i < cnt; i++) {
                printf("%d %d %I64d\n",e[i].from,e[i].to,INF);
            }
        }
        else {
            int _tot = tot;
            int index = -1;
            for(int i = 0; i < cnt; i++) {
                u = e[i].from;
                v = e[i].to;
                addedge(u,v,1);
                addedge(v,u,1);
                spfa(s);
                if(dis[t] <= l) {
                    index = i;
                    w = 1 + l - dis[t];
                    break;
                }
            }
            if(index == -1) {
                printf("NO\n");
            }
            else {
                printf("YES\n");
                for(int i = 0; i < _tot; i += 2) {
                    printf("%d %d %I64d\n",edge[i].from,edge[i].to,edge[i].w);
                }
                for(int i = 0; i < index; i++) {
                    printf("%d %d %d\n",e[i].from,e[i].to,1);
                }
                printf("%d %d %d\n",e[index].from,e[index].to,w);
                for(int i = index + 1; i < cnt; i++) {
                    printf("%d %d %I64d\n",e[i].from,e[i].to,INF);
                }
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/GYH0730/article/details/82935981
今日推荐