CodeForces 567E President and Roads

Description

Berland has n cities, the capital is located in city s, and the historic home town of the President is in city t (s ≠ t). The cities are connected by one-way roads, the travel time for each of the road is a positive integer.

Once a year the President visited his historic home town t, for which his motorcade passes along some path from s to t (he always returns on a personal plane). Since the president is a very busy man, he always chooses the path from s to t, along which he will travel the fastest.

The ministry of Roads and Railways wants to learn for each of the road: whether the President will definitely pass through it during his travels, and if not, whether it is possible to repair it so that it would definitely be included in the shortest path from the capital to the historic home town of the President. Obviously, the road can not be repaired so that the travel time on it was less than one. The ministry of Berland, like any other, is interested in maintaining the budget, so it wants to know the minimum cost of repairing the road. Also, it is very fond of accuracy, so it repairs the roads so that the travel time on them is always a positive integer.

Input

The first lines contain four integers n, m, s and t (2 ≤ n ≤ 105; 1 ≤ m ≤ 105; 1 ≤ s, t ≤ n) — the number of cities and roads in Berland, the numbers of the capital and of the Presidents’ home town (s ≠ t).

Next m lines contain the roads. Each road is given as a group of three integers ai, bi, li (1 ≤ ai, bi ≤ n; ai ≠ bi; 1 ≤ li ≤ 106) — the cities that are connected by the i-th road and the time needed to ride along it. The road is directed from city ai to city bi.

The cities are numbered from 1 to n. Each pair of cities can have multiple roads between them. It is guaranteed that there is a path from s to t along the roads.

Output

Print m lines. The i-th line should contain information about the i-th road (the roads are numbered in the order of appearance in the input).

If the president will definitely ride along it during his travels, the line must contain a single word “YES” (without the quotes).

Otherwise, if the i-th road can be repaired so that the travel time on it remains positive and then president will definitely ride along it, print space-separated word “CAN” (without the quotes), and the minimum cost of repairing.

If we can’t make the road be such that president will definitely ride along it, print “NO” (without the quotes).

Sample Input
Input

6 7 1 6
1 2 2
1 3 10
2 3 7
2 4 8
3 5 3
4 5 2
5 6 1

Output

YES
CAN 2
CAN 1
CAN 1
CAN 1
CAN 1
YES

Input

3 3 1 3
1 2 10
2 3 10
1 3 100

Output

YES
YES
CAN 81

Input

2 2 1 2
1 2 1
1 2 2

Output

YES
NO

Hint

The cost of repairing the road is the difference between the time needed to ride along it before and after the repairing.

In the first sample president initially may choose one of the two following ways for a ride: 1 → 2 → 4 → 5 → 6 or 1 → 2 → 3 → 5 → 6.

题目大意:总统要回家,会经过一些街道,每条街道都是单向的并且拥有权值。现在,为了让总统更好的回家,要对每一条街道进行操作:1)如果该街道一定在最短路上,则输出“YES”。2)如果该街道修理过后,该边所在的最短路可以取代原先的最短路,则输出“CAN x”,x是修改该街道的花费,就是权值减小的值。3)如果该街道是一条不连通的街道,或者修改过后权值小于等于0,则输出“NO”。

解题思路:正向取边,求一次最短路得到d1[], 然后反向取边,再求一次最短路得到d2[]。接着开始判断每一条边是否在最短路上。初始最短路为Min,当d1[u]+d2[v]+dis==Min时,先判断该边是否一定为最短路上的边,是的话输出“YES”,否则在判断该边的权值是否大于1,是的话输出“CAN 1”,否则输出“NO”。当d1[u]+d2[v]+dis>Min时,先判断两段路的差值加一是否会大于等于该边的差值,是的话,输出“NO”,否则输出“CAN 差值加一”,其余情况均输出“NO”。还有一个问题,如何判断边是否一定在最短路上。先把最短路取出,重新建一张无向图,然后用tarjan算法求出哪些边是桥。桥就是一定在最短路上的边。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <queue>
using namespace std;
typedef long long ll;

const int N = 200005;
const int M = 400005;
const ll INF = 1e17;
int n, m, s, t;
ll Min;
int vis[2][N];
ll d[2][N];
int en;
int head[3][M], no[M], fa[M];
int DFN[M], LOW[M], DN;
int tj[M], FLAG;

struct POS{
    int u;
    ll d;
    bool operator < (const POS& x) const {
        return d > x.d; 
    }
};
struct node {  
    int to, next;
    ll dis;
}edge[3][M];  
struct REC{
    int u, v, e;
    ll c;
}rec[M];

void init() {
    en = 0;
    DN = 0;
    memset(head, -1, sizeof(head));
}

void addEdge(int u, int v, ll x, int flag, ll d) {  
    if (d != INF) rec[d].u = u, rec[d].v = v, rec[d].c = x, rec[d].e = en;
    edge[flag][en].to = v;  
    edge[flag][en].next = head[flag][u];  
    edge[flag][en].dis = x;  
    head[flag][u] = en++;  
}  
void addEdgeMD(int u, int v, ll x, int flag, int d) {  
    edge[flag][en].to = v;  
    edge[flag][en].next = head[flag][u];  
    edge[flag][en].dis = x;  
    no[en] = d;
    head[flag][u] = en++;  

    edge[flag][en].to = u;  
    edge[flag][en].next = head[flag][v];  
    edge[flag][en].dis = x;  
    no[en] = d;
    head[flag][v] = en++;   
}

void Dijkstra(int flag) {
    priority_queue<POS> q;
    for (int i = 1; i <= n; i++) {
        d[flag][i] = INF;   
        vis[flag][i] = 0;
    }
    d[flag][s] = 0;
    q.push((POS){s, 0});
    while (!q.empty()) {
        int u = q.top().u;
        q.pop();    
        if (vis[flag][u]) continue;
        vis[flag][u] = 1;
        for (int i = head[flag][u]; i != -1; i = edge[flag][i].next) {
            int v = edge[flag][i].to;   
            if (d[flag][v] > d[flag][u] + edge[flag][i].dis) {
                d[flag][v] = d[flag][u] + edge[flag][i].dis;
                q.push((POS){v, d[flag][v]});
            }
        }
    }
}
void input() {
    int a, b;
    ll c;
    for (int i = 0; i < m; i++) {
        scanf("%d %d %lld", &a, &b, &c);    
        addEdge(a, b, c, 0, i);
        addEdge(b, a, c, 1, INF);
    }
}

void getD() {
    Dijkstra(0);
    swap(s, t);
    Dijkstra(1);
    swap(s, t);
    Min = d[0][t];
}

void tarjan(int u) {
    DFN[u] = LOW[u] = DN++;     
    for (int i = head[2][u]; i != -1; i = edge[2][i].next) {
        int v = edge[2][i].to;  
        if (!DFN[v]) {
            fa[v] = no[i];
            tarjan(v);  
            LOW[u] = min(LOW[u], LOW[v]);
            if (LOW[v] > DFN[u]) tj[fa[v]] = 1;
        } else if (fa[u] != no[i]) {
            LOW[u] = min(LOW[u], DFN[v]);
        }
    }
}

void buildMD() {
    en = 0;
    for (int i = 0; i < m; i++) {
        REC r = rec[i];
        if (d[0][r.u] + d[1][r.v] + r.c == Min) {
            addEdgeMD(r.u, r.v, r.c, 2, i);
        } 
    }
}

void solve() {
    for (int i = 0; i < m; i++) {
        REC r = rec[i];
        ll D = d[0][r.u] + d[1][r.v] + r.c;
        if (d[0][r.u] == INF || d[1][r.v] == INF) {
            printf("NO\n"); 
            continue;
        }
        if (tj[i]) printf("YES\n");
        else if (D == Min && r.c > 1) printf("CAN 1\n");
        else if (D > Min) {
            int temp = D - Min + 1; 
            if (r.c <= temp) printf("NO\n");
            else printf("CAN %d\n", temp);
        } else printf("NO\n");
    }
}

int main() {
    scanf("%d %d %d %d", &n, &m, &s, &t);
    init();
    input();
    getD();
    buildMD();
    tarjan(s);
    solve();
    return 0;
}