Complete The Graph CodeForces - 716D 最短路+暴力 很好的一道题

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 0 then 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.

Example
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".





做法:

一开始把所有的0边先标记好,之后把0变为无穷大来计算最短路。

当所有的未知边都是无穷大的时候,我们的最短路还是小了,那么我们是无解的,我们没办法更大了。

如果正好等于,那么我们直接输出即可。

如果大于,说明我们有些未知边不能设置为无穷大。那么应该设为什么呢,我们暴力枚举。

我们暴力枚举每一条未知边,把某条边设为1,再求最短路。如果当前的最短路还是大了,那么我们继续变下一条边为1.

如果等于,那么直接输出。如果小于,计算出小了多少。那么我们就应该把刚刚更改为1的那条边加上小于的数值即可。


这道题有个迷之超时....记录未知边时放到if里就超时,不放就不超时...无奈..

#include
#include
#include
#include
#include
#include
#include
#define inf 0x7f7f7f
using namespace std;
const int maxn = 1e5+10;
struct node
{
    int u;
    int to;
    int next;
    long long cost;
} edge[maxn<<1];
int head[maxn],tot;
int n,m,s,t;
long long path[maxn];
bool vis[maxn];


vector kongbai;
long long L;


void init()
{
    memset(head,-1,sizeof(head));
    tot = 0;
    kongbai.clear();
}


void addedge(int u,int v,long long cost)
{
    edge[tot].u = u;
    edge[tot].to = v;
    edge[tot].next = head[u];
    edge[tot].cost = cost;
    head[u] = tot++;
}




long long spfa(int s,int t)
{
    memset(vis,false,sizeof(vis));
    memset(path,inf,sizeof(path));
    path[s] = 0;
    vis[s] = true;
    queue sk;
    sk.push(s);
    while(!sk.empty())
    {
        int u = sk.front();
        sk.pop();
        vis[u] = false;
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int to = edge[i].to;
            if(path[to]>path[u] + edge[i].cost)
            {
                path[to] = path[u] + edge[i].cost;
                if(!vis[to])
                {
                    vis[to] = true;
                    sk.push(to);
                }
            }
        }
    }
    return path[t];
}


int main()
{
    init();
    cin>>n>>m>>L>>s>>t;
    int a,b;
    long long cost;
    for(int i=0; i    {
        cin>>a>>b>>cost;
        if(!cost)
        {
            cost=1e9;
            kongbai.push_back(tot);


        }
        addedge(a,b,cost);
        addedge(b,a,cost);


    }
    //全都变为最大,求最短路


    long long dangiqnazuiduanlu=spfa(s,t);
    if(dangiqnazuiduanlu    {
        cout<<"NO"<        return 0;
    }
    else if(dangiqnazuiduanlu==L)//如果相等
    {
       cout<<"YES"<       for(int i=0; i          cout<        return 0;
    }
    else//否则
    {
        int numm=kongbai.size();
        for(int i=0; i        {
            int now = kongbai[i];//第几条路可以带换
            edge[now].cost = edge[now^1].cost = 1;
            dangiqnazuiduanlu=spfa(s,t);
            if(dangiqnazuiduanlu<=L)//小了,我们让当前更改的多加点即可
            {
                edge[now].cost = edge[now^1].cost = L - dangiqnazuiduanlu + 1;
                 cout<<"YES"<                for(int i=0; i                cout<                return 0;
            }


        }
    }
    cout<<"NO"<    return 0;
}

你可能感兴趣的:(大三ACM,-,图)