CodeForces - 715 B. Complete The Graph(dijkstra+暴力)

B. 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 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.

Examples
input
Copy
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
Copy
2 1 123456789 0 1
0 1 0
output
YES
0 1 123456789
input
Copy
2 1 999999999 1 0
0 1 1000000000
output
NO


題意:n個點,m條邊,起點s,終點t,當邊的權值爲0時,可以改變爲任意的權值,求是否可以通過改變權值爲0的邊,使s到t的最短路長度爲L


由於求的是最短路首先想到最短路問題,

當改變一條邊的權值後,s到t的最短路也會發生變化,於是此時最短路要重新計算

共有兩種情況:

1.不經過權值爲0的邊,此時的最短路已經<L,那麼這種情況肯定是輸出NO

2不經過權值爲0的邊,此時的最短路>=L,此時就要考慮加上這些權值爲0的邊,使得最短路變小,滿足條件

當經過一條權值爲0的邊,可以先將該邊賦權值爲1(因爲題目要求邊權爲正整數),求出最短距離,如果此時的最短距離<L,表示此時該邊一定在最短路徑中,將該邊權改爲L-dis[t]+1,使最短路爲L

然後暴力將每一個權值爲0的邊加入圖即可

若加入所有邊後,此時的最短距離仍>L,輸出NO

否則,輸出YES

#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int N=1e3+20;
int n,m,s,t,L,first[N],tot;
ll dis[N];
bool vis[N];
struct node
{
    int v,next,flag;
    ll w;
} e[N*20];
void add(int u,int v,ll w)
{
    e[tot].v=v;
    e[tot].w=w;
    if(w==0)e[tot].flag=1;
    e[tot].next=first[u];
    first[u]=tot++;
}
struct point
{
    point(int a,ll b)
    {
        x=a,val=b;
    }
    int x;
    ll val;
    bool friend operator <(point A,point B)
    {
        return A.val>B.val;
    }
};
void dijkstra()
{
    for(int i=0;i<n;i++)dis[i]=1000000000000000000;
    priority_queue<point>q;
    dis[s]=0;
    q.push(point(s,0));
    while(!q.empty())
    {
        point u=q.top();
        q.pop();
        if(dis[u.x]<u.val)continue;
        for(int i=first[u.x]; ~i; i=e[i].next)
        {
            int v=e[i].v;
            if(e[i].w==0)continue;
            if(dis[v]>dis[u.x]+e[i].w)
            {
                dis[v]=dis[u.x]+e[i].w;
                q.push(point(v,dis[v]));
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    mem(first,-1);
    int u,v;
    ll w;
    cin>>n>>m>>L>>s>>t;
    for(int i=0; i<m; i++)
    {
        cin>>u>>v>>w;
        add(u,v,w);
        add(v,u,w);
    }
    dijkstra();
    if(dis[t]<L)puts("NO");//不經過權值爲0的邊,最短路已經<L
    else//>=L的情況
    {
       for(int i=0;i<tot;i+=2)
       {
           if(!e[i].flag)continue;
           e[i].w=e[i^1].w=1;
           dijkstra();//暴力將每條邊都加入圖,求得最短路
           if(dis[t]<L)//將最小距離補夠L
            e[i].w=e[i^1].w=L-dis[t]+1;
       }
       if(dis[t]>L)puts("NO");//加完所有邊後距離仍>L
       else//不會出現<L的情況,因爲每次都補夠了L
       {
           puts("YES");
           for(int i=0;i<tot;i+=2)
            printf("%d %d %lld\n",e[i^1].v,e[i].v,e[i].w);
       }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章