/*
ID: hepic
PROG: lamps
LANG: C++11
*/
#include<bits/stdc++.h>

#define FOR(i, a, b) for(auto i=a; i!=b+1-2*(a>b); i+=1-2*(a>b))
#define REP(i, a, b) for(auto i=a-(a>b); i!=b-(a>b); i+=1-2*(a>b))
#define ALL(v) v.begin(),v.end()
#define mp(a, b) make_pair(a, b)
#define pb(a) push_back(a)
#define pf(a) push_front(a)
#define eb(a, b) emplace_back(a, b)
#define fir first
#define sec second
#define what_is(x) cout<<#x<<" is "<<x<<endl;
#define min3(a,b,c) min(min(a,b),c)
#define max3(a,b,c) max(max(a,b),c)
#define SIZE 100010
#define MAXN 1000000000
#define NUM 200010
#define PI acos(-1)
#define open_read1 freopen("C:\\Users\\Hepic\\Desktop\\a.txt","r",stdin)
#define open_write1 freopen("C:\\Users\\Hepic\\Desktop\\b.txt","w",stdout)
#define open_read freopen("cruise.in","r",stdin)
#define open_write freopen("cruise.out","w",stdout)

using namespace std;

typedef long long LL;
typedef pair<int,int> PII;
typedef pair<int, PII> PIPII;
typedef pair<PII, PII> PPIIPII;
typedef pair<LL,LL> PLL;

template<typename T, typename T1>
ostream& operator << (ostream &out, pair<T, T1> obj)
{
    return out<<"("<<obj.first<<","<<obj.second<<")";
}

template<typename T, typename T1>
ostream& operator << (ostream &out, map<T, T1> cont)
{
    typename map<T, T1>::const_iterator itr = cont.begin();
    typename map<T, T1>::const_iterator ends = cont.end();

    for(; itr!=ends; ++itr)
        out<<*itr<<" ";
    out<<endl;
}

template<typename T>
ostream& operator << (ostream &out, set<T> cont)
{
    typename set<T>::const_iterator itr = cont.begin();
    typename set<T>::const_iterator ends = cont.end();

    for(; itr!=ends; ++itr)
        out<<*itr<<" ";
    out<<endl;
}

template<typename T, template<typename ELEM, typename ALLOC=allocator<ELEM>> class CONT>
ostream& operator << (ostream &out, CONT<T> cont)
{
    typename CONT<T>::const_iterator itr = cont.begin();
    typename CONT<T>::const_iterator ends = cont.end();

    for(; itr!=ends; ++itr)
        out<<*itr<<" ";
    out<<endl;
}

template<typename T>
T gcd(T a, T b)
{
    T min_v = min(a, b);
    T max_v = max(a, b);

    while(min_v)
    {
        T temp = max_v % min_v;
        max_v = min_v;
        min_v = temp;
    }

    return max_v;
}

template<typename T>
T lcm(T a, T b)
{
    return (a*b) / gcd(a, b);
}

/*#################################################################################################################
#################################################################################################################
#################################################################################################################
#################################################################################################################*/

int N, M, CAPITAL, HOME, A, B, C;
int home_dst[SIZE], capital_dst[SIZE];
int home_cnt[SIZE], capital_cnt[SIZE];
bool visited[SIZE];
vector<PII> capital_graph[SIZE], home_graph[SIZE];
vector<PIPII> roads;
priority_queue<PII, vector<PII>, greater<PII>> que;

void initialize()
{
    while(!que.empty())
        que.pop();

    REP(i, 0, SIZE)
        visited[i] = false;
}

void dijkstra(vector<PII> *graph, int nde, int *Tdistances, int *Tcounts)
{
    initialize();
    que.push(mp(0, nde));

    while(!que.empty())
    {
        int node = que.top().sec;
        int dst = que.top().fir;
        que.pop();

        if(!visited[node])
        {
            Tcounts[node] = 1;
            Tdistances[node] = dst;

            visited[node] = true;
        }

        else if(visited[node]  &&  dst == Tdistances[node])
            ++Tcounts[node];

        REP(i, 0, graph[node].size())
        {
            int conn_node = graph[node][i].fir;
            int conn_dst = graph[node][i].sec;

           // if(!visited[conn_node])
                que.push(mp(dst+conn_dst, conn_node));
        }
    }
}

int main()
{
    //open_read1;
    scanf("%d%d%d%d", &N, &M, &CAPITAL, &HOME);

    REP(i, 0, M)
    {
        scanf("%d%d%d", &A, &B, &C);

        capital_graph[A].pb(mp(B, C));
        home_graph[B].pb(mp(A, C));

        roads.pb(mp(C, mp(A, B)));
    }

    dijkstra(capital_graph, CAPITAL, capital_dst, capital_cnt);
    dijkstra(home_graph, HOME, home_dst, home_cnt);

    REP(i, 0, M)
    {
        int len = roads[i].fir;
        int cityA = roads[i].sec.fir;
        int cityB = roads[i].sec.sec;

        int dist = capital_dst[cityA] + len + home_dst[cityB];
        int cnt = capital_cnt[cityA] * home_cnt[cityB];

        if(dist == capital_dst[HOME])
        {
            if(cnt == capital_cnt[HOME])
                printf("YES\n");

            else if(cnt < capital_cnt[HOME])
            {
                if(len > 1)
                    printf("CAN 1\n");

                else if(len <= 1)
                    printf("NO\n");
            }
        }

        else if(dist > capital_dst[HOME])
        {
            int diff = abs(capital_dst[HOME] - len - 1);

            if(len-diff > 1)
                printf("CAN %d\n", diff);

            else
                printf("NO\n");
        }
    }

    return 0;
}


/*
ID: hepic
PROG: ariprog
LANG: C++11
*/
#include<bits/stdc++.h>

#define FOR(i, a, b) for(auto i=a; i!=b+1-2*(a>b); i+=1-2*(a>b))
#define REP(i, a, b) for(auto i=a-(a>b); i!=b-(a>b); i+=1-2*(a>b))
#define ALL(v) v.begin(),v.end()
#define mp(a, b) make_pair(a, b)
#define pb(a) push_back(a)
#define pf(a) push_front(a)
#define eb(a, b) emplace_back(a, b)
#define fir first
#define sec second
#define what_is(x) cout<<#x<<" is "<<x<<endl;
#define type(x) typeid(x).name()
#define ms(arr, val) memset(arr, val, sizeof(arr))
#define min3(a,b,c) min(min(a,b),c)
#define max3(a,b,c) max(max(a,b),c)
#define SIZE 100010
#define MAXN 1000000007
#define NUM 25
#define PI acos(-1)
#define open_read1 freopen("C:\\Users\\Hepic\\Desktop\\a.txt", "r", stdin)
#define open_write1 freopen("C:\\Users\\Hepic\\Desktop\\b.txt", "w", stdout)
#define open_read freopen("ariprog.in", "r", stdin)
#define open_write freopen("ariprog.out", "w", stdout)

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<double, double> PDD;
typedef pair<int, int> PII;
typedef pair<int, PII> PIPII;
typedef pair<PII, PII> PPIIPII;
typedef pair<LL, LL> PLL;
typedef pair<LL, PLL> PLPLL;

template<typename T, typename T1>
ostream& operator << (ostream &out, pair<T, T1> obj)
{
    return out<<"("<<obj.first<<","<<obj.second<<")";
}

template<typename T, typename T1>
ostream& operator << (ostream &out, map<T, T1> cont)
{
    typename map<T, T1>::const_iterator itr = cont.begin();
    typename map<T, T1>::const_iterator ends = cont.end();

    for(; itr!=ends; ++itr)
        out<<*itr<<" ";
    out<<endl;
}

template<typename T>
ostream& operator << (ostream &out, set<T> cont)
{
    typename set<T>::const_iterator itr = cont.begin();
    typename set<T>::const_iterator ends = cont.end();

    for(; itr!=ends; ++itr)
        out<<*itr<<" ";
    out<<endl;
}

template<typename T>
ostream& operator << (ostream &out, multiset<T> cont)
{
    typename multiset<T>::const_iterator itr = cont.begin();
    typename multiset<T>::const_iterator ends = cont.end();

    for(; itr!=ends; ++itr)
        out<<*itr<<" ";
    out<<endl;
}

template<typename T, template<typename ELEM, typename ALLOC=allocator<ELEM>> class CONT>
ostream& operator << (ostream &out, CONT<T> cont)
{
    typename CONT<T>::const_iterator itr = cont.begin();
    typename CONT<T>::const_iterator ends = cont.end();

    for(; itr!=ends; ++itr)
        out<<*itr<<" ";
    out<<endl;
}

template<typename T, unsigned int N, typename CTy, typename CTr>
typename enable_if<!is_same<T, char>::value, basic_ostream<CTy, CTr> &>::type
operator << (basic_ostream<CTy, CTr> &out, const T (&arr)[N])
{
     REP(i, 0, N)
        out<<arr[i]<<" ";
    out<<endl;
}

template<typename T>
T gcd(T a, T b)
{
    T min_v = min(a, b);
    T max_v = max(a, b);

    while(min_v)
    {
        T temp = max_v % min_v;
        max_v = min_v;
        min_v = temp;
    }

    return max_v;
}

template<typename T>
T lcm(T a, T b)
{
    return (a*b) / gcd(a, b);
}

template<typename T>
T fast_exp_pow(T base, T exp, T mod)
{
    LL res = 1;

    while(exp)
    {
        if(exp&1)
        {
            res *= base;
            res %= mod;
        }

        exp >>= 1;
        base *= base;
        base %= mod;
    }

    return res;
}

/*#################################################################################################################
#################################################################################################################
#################################################################################################################
#################################################################################################################*/

int N, M, S, T, A, B, C, min_dst, all_ways;
int distanceS[SIZE], distanceT[SIZE], waysS[SIZE], waysT[SIZE];
bool visited[SIZE];
vector<PII> graphS[SIZE], graphT[SIZE];
vector<PIPII> roads;
priority_queue<PII, vector<PII>, greater<PII>> que;

void dijkstra(int Tbeg, vector<PII> *graph, int *dists, int *ways)
{
    ms(visited, false);
    dists[Tbeg] = 0;
    ways[Tbeg] = 1;

    que.push(mp(0, Tbeg));

    while(!que.empty())
    {
        int cost = que.top().fir;
        int node = que.top().sec;
        que.pop();

        visited[node] = true;

        REP(i, 0, graph[node].size())
        {
            int conn_node = graph[node][i].fir;
            int new_cost = graph[node][i].sec;

            if(!visited[conn_node])
            {
                if(!dists[conn_node]  ||  dists[conn_node] > cost+new_cost)
                {
                    que.push(mp(cost+new_cost, conn_node));
                    dists[conn_node] =  cost+new_cost;
                    ways[conn_node] = ways[node];
                }

                else if(dists[conn_node] == cost+new_cost)
                    ways[conn_node] += ways[node];
            }
        }
    }
}

int main()
{
    //open_read1;
    scanf("%d%d%d%d", &N, &M, &S, &T);

    REP(i, 0, M)
    {
        scanf("%d%d%d", &A, &B, &C);

        graphS[A].eb(B, C);
        graphT[B].eb(A, C);
        roads.eb(C, mp(A, B));
    }

    dijkstra(S, graphS, distanceS, waysS);
    dijkstra(T, graphT, distanceT, waysT);
    min_dst = distanceS[T];
    all_ways = waysS[T];

    REP(i, 0, M)
    {
        int node1 = roads[i].sec.fir;
        int node2 = roads[i].sec.sec;
        int dst = distanceS[node1] + roads[i].fir + distanceT[node2];
        int ways = waysS[node1] * waysT[node2];

        if(!ways)
        {
            printf("NO\n");
            continue;
        }

        if(dst == min_dst)
        {
            if(ways == all_ways)
                printf("YES\n");

            else if(ways < all_ways)
            {
                if(roads[i].fir > 1)
                    printf("CAN 1\n");
                else
                    printf("NO\n");
            }
        }

        else if(dst > min_dst)
        {
            int val = dst - min_dst + 1;

            if(roads[i].fir - val >= 1)
                printf("CAN %d\n", val);
            else
                printf("NO\n");
        }
    }

    return 0;
}


/*
ID: hepic
PROG: lamps
LANG: C++11
*/
#include<bits/stdc++.h>

#define FOR(i, a, b) for(auto i=a; i!=b+1-2*(a>b); i+=1-2*(a>b))
#define REP(i, a, b) for(auto i=a-(a>b); i!=b-(a>b); i+=1-2*(a>b))
#define ALL(v) v.begin(),v.end()
#define mp(a, b) make_pair(a, b)
#define pb(a) push_back(a)
#define pf(a) push_front(a)
#define eb(a, b) emplace_back(a, b)
#define fir first
#define sec second
#define what_is(x) cout<<#x<<" is "<<x<<endl;
#define min3(a,b,c) min(min(a,b),c)
#define max3(a,b,c) max(max(a,b),c)
#define SIZE 100010
#define MAXN (1e8 + 7)
#define NUM 200010
#define PI acos(-1)
#define open_read1 freopen("C:\\Users\\Hepic\\Desktop\\a.txt","r",stdin)
#define open_write1 freopen("C:\\Users\\Hepic\\Desktop\\b.txt","w",stdout)
#define open_read freopen("cruise.in","r",stdin)
#define open_write freopen("cruise.out","w",stdout)

using namespace std;

typedef long long LL;
typedef pair<int,int> PII;
typedef pair<int, PII> PIPII;
typedef pair<PII, PII> PPIIPII;
typedef pair<LL, LL> PLL;
typedef pair<LL, PLL> PLPLL;

template<typename T, typename T1>
ostream& operator << (ostream &out, pair<T, T1> obj)
{
    return out<<"("<<obj.first<<","<<obj.second<<")";
}

template<typename T, typename T1>
ostream& operator << (ostream &out, map<T, T1> cont)
{
    typename map<T, T1>::const_iterator itr = cont.begin();
    typename map<T, T1>::const_iterator ends = cont.end();

    for(; itr!=ends; ++itr)
        out<<*itr<<" ";
    out<<endl;
}

template<typename T>
ostream& operator << (ostream &out, set<T> cont)
{
    typename set<T>::const_iterator itr = cont.begin();
    typename set<T>::const_iterator ends = cont.end();

    for(; itr!=ends; ++itr)
        out<<*itr<<" ";
    out<<endl;
}

template<typename T, template<typename ELEM, typename ALLOC=allocator<ELEM>> class CONT>
ostream& operator << (ostream &out, CONT<T> cont)
{
    typename CONT<T>::const_iterator itr = cont.begin();
    typename CONT<T>::const_iterator ends = cont.end();

    for(; itr!=ends; ++itr)
        out<<*itr<<" ";
    out<<endl;
}

template<typename T>
T gcd(T a, T b)
{
    T min_v = min(a, b);
    T max_v = max(a, b);

    while(min_v)
    {
        T temp = max_v % min_v;
        max_v = min_v;
        min_v = temp;
    }

    return max_v;
}

template<typename T>
T lcm(T a, T b)
{
    return (a*b) / gcd(a, b);
}

/*#################################################################################################################
#################################################################################################################
#################################################################################################################
#################################################################################################################*/

LL N, M, CAPITAL, HOME, A, B, C;
LL home_dst[SIZE], capital_dst[SIZE];
LL home_cnt[SIZE], capital_cnt[SIZE];
bool visited[SIZE];
vector<PLL> capital_graph[SIZE], home_graph[SIZE];
vector<PLPLL> roads;
priority_queue<PLL, vector<PLL>, greater<PLL>> que;
const LL mod = 1e8+7;

void initialize()
{
    while(!que.empty())
        que.pop();

    REP(i, 0, SIZE)
        visited[i] = false;
}

void dijkstra(vector<PLL> *graph, LL nde, LL *Tdistances, LL *Tcounts)
{
    initialize();
    que.push(mp(0, nde));
    Tdistances[nde] = 0;
    Tcounts[nde] = 1;

    while(!que.empty())
    {
        LL node = que.top().sec;
        LL dst = que.top().fir;
        que.pop();

        visited[node] = true;

        REP(i, 0, graph[node].size())
        {
            LL conn_node = graph[node][i].fir;
            LL conn_dst = graph[node][i].sec;

            if(!visited[conn_node])
            {
                if(!Tdistances[conn_node]  ||  Tdistances[conn_node] > dst+conn_dst)
                {
                    que.push(mp(dst+conn_dst, conn_node));
                    Tdistances[conn_node] = dst+conn_dst;
                    Tcounts[conn_node] = Tcounts[node];
                }

                else if(Tdistances[conn_node] == dst+conn_dst)
                    Tcounts[conn_node] = (Tcounts[conn_node] + Tcounts[node]) % mod;
            }
        }
    }
}

int main()
{
    //open_read1;
    scanf("%I64d%I64d%I64d%I64d", &N, &M, &CAPITAL, &HOME);

    REP(i, 0, M)
    {
        scanf("%I64d%I64d%I64d", &A, &B, &C);

        capital_graph[A].pb(mp(B, C));
        home_graph[B].pb(mp(A, C));

        roads.pb(mp(C, mp(A, B)));
    }

    dijkstra(capital_graph, CAPITAL, capital_dst, capital_cnt);
    dijkstra(home_graph, HOME, home_dst, home_cnt);

    REP(i, 0, M)
    {
        LL len = roads[i].fir;
        LL cityA = roads[i].sec.fir;
        LL cityB = roads[i].sec.sec;

        LL dist = capital_dst[cityA] + len + home_dst[cityB];
        LL cnt_ways = (capital_cnt[cityA] * home_cnt[cityB]) % mod;

        if(!cnt_ways)
        {
            printf("NO\n");
            continue;
        }

        if(dist == capital_dst[HOME])
        {
            if(cnt_ways == capital_cnt[HOME])
                printf("YES\n");

            else if(cnt_ways < capital_cnt[HOME])
            {
                if(len > 1)
                    printf("CAN 1\n");

                else if(len <= 1)
                    printf("NO\n");
            }
        }

        else if(dist > capital_dst[HOME])
        {
            LL diff = dist - capital_dst[HOME] + 1;

            if(len-diff >= 1)
                printf("CAN %I64d\n", diff);

            else
                printf("NO\n");
        }
    }

    return 0;
}


/*
ID: hepic
PROG: lamps
LANG: C++11
*/
#include<bits/stdc++.h>

#define FOR(i, a, b) for(auto i=a; i!=b+1-2*(a>b); i+=1-2*(a>b))
#define REP(i, a, b) for(auto i=a-(a>b); i!=b-(a>b); i+=1-2*(a>b))
#define ALL(v) v.begin(),v.end()
#define mp(a, b) make_pair(a, b)
#define pb(a) push_back(a)
#define pf(a) push_front(a)
#define eb(a, b) emplace_back(a, b)
#define fir first
#define sec second
#define what_is(x) cout<<#x<<" is "<<x<<endl;
#define min3(a,b,c) min(min(a,b),c)
#define max3(a,b,c) max(max(a,b),c)
#define SIZE 100010
#define MAXN 1000000000
#define NUM 200010
#define PI acos(-1)
#define open_read1 freopen("C:\\Users\\Hepic\\Desktop\\a.txt","r",stdin)
#define open_write1 freopen("C:\\Users\\Hepic\\Desktop\\b.txt","w",stdout)
#define open_read freopen("cruise.in","r",stdin)
#define open_write freopen("cruise.out","w",stdout)

using namespace std;

typedef long long LL;
typedef pair<int,int> PII;
typedef pair<int, PII> PIPII;
typedef pair<PII, PII> PPIIPII;
typedef pair<LL, LL> PLL;
typedef pair<LL, PLL> PLPLL;

template<typename T, typename T1>
ostream& operator << (ostream &out, pair<T, T1> obj)
{
    return out<<"("<<obj.first<<","<<obj.second<<")";
}

template<typename T, typename T1>
ostream& operator << (ostream &out, map<T, T1> cont)
{
    typename map<T, T1>::const_iterator itr = cont.begin();
    typename map<T, T1>::const_iterator ends = cont.end();

    for(; itr!=ends; ++itr)
        out<<*itr<<" ";
    out<<endl;
}

template<typename T>
ostream& operator << (ostream &out, set<T> cont)
{
    typename set<T>::const_iterator itr = cont.begin();
    typename set<T>::const_iterator ends = cont.end();

    for(; itr!=ends; ++itr)
        out<<*itr<<" ";
    out<<endl;
}

template<typename T, template<typename ELEM, typename ALLOC=allocator<ELEM>> class CONT>
ostream& operator << (ostream &out, CONT<T> cont)
{
    typename CONT<T>::const_iterator itr = cont.begin();
    typename CONT<T>::const_iterator ends = cont.end();

    for(; itr!=ends; ++itr)
        out<<*itr<<" ";
    out<<endl;
}

template<typename T>
T gcd(T a, T b)
{
    T min_v = min(a, b);
    T max_v = max(a, b);

    while(min_v)
    {
        T temp = max_v % min_v;
        max_v = min_v;
        min_v = temp;
    }

    return max_v;
}

template<typename T>
T lcm(T a, T b)
{
    return (a*b) / gcd(a, b);
}

/*#################################################################################################################
#################################################################################################################
#################################################################################################################
#################################################################################################################*/

LL N, M, CAPITAL, HOME, A, B, C;
LL home_dst[SIZE], capital_dst[SIZE];
LL home_cnt[SIZE], capital_cnt[SIZE];
bool visited[SIZE];
vector<PLL> capital_graph[SIZE], home_graph[SIZE];
vector<PLPLL> roads;
priority_queue<PLL, vector<PLL>, greater<PLL>> que;

void initialize()
{
    while(!que.empty())
        que.pop();

    REP(i, 0, SIZE)
        visited[i] = false;
}

void dijkstra(vector<PLL> *graph, LL nde, LL *Tdistances, LL *Tcounts)
{
    initialize();
    que.push(mp(0, nde));

    while(!que.empty())
    {
        LL node = que.top().sec;
        LL dst = que.top().fir;
        que.pop();

        if(!visited[node])
        {
            Tcounts[node] = 1;
            Tdistances[node] = dst;

            visited[node] = true;
        }

        else if(visited[node]  &&  dst == Tdistances[node])
            ++Tcounts[node];

        if(!visited[node])
        {
            REP(i, 0, graph[node].size())
            {
                LL conn_node = graph[node][i].fir;
                LL conn_dst = graph[node][i].sec;

                if(!visited[conn_node])
                    que.push(mp(dst+conn_dst, conn_node));
            }
        }
    }
}

int main()
{
    //open_read1;
    scanf("%I64d%I64d%I64d%I64d", &N, &M, &CAPITAL, &HOME);

    REP(i, 0, M)
    {
        scanf("%I64d%I64d%I64d", &A, &B, &C);

        capital_graph[A].pb(mp(B, C));
        home_graph[B].pb(mp(A, C));

        roads.pb(mp(C, mp(A, B)));
    }

    dijkstra(capital_graph, CAPITAL, capital_dst, capital_cnt);
    dijkstra(home_graph, HOME, home_dst, home_cnt);

    REP(i, 0, M)
    {
        LL len = roads[i].fir;
        LL cityA = roads[i].sec.fir;
        LL cityB = roads[i].sec.sec;

        LL dist = capital_dst[cityA] + len + home_dst[cityB];
        LL cnt_ways = capital_cnt[cityA] * home_cnt[cityB];

        if(!cnt_ways)
        {
            printf("NO\n");
            continue;
        }

        if(dist == capital_dst[HOME])
        {
            if(cnt_ways == capital_cnt[HOME])
                printf("YES\n");

            else if(cnt_ways < capital_cnt[HOME])
            {
                if(len > 1)
                    printf("CAN 1\n");

                else if(len <= 1)
                    printf("NO\n");
            }
        }

        else if(dist > capital_dst[HOME])
        {
            LL diff = dist - capital_dst[HOME] + 1;

            if(len-diff >= 1)
                printf("CAN %I64d\n", diff);

            else
                printf("NO\n");
        }
    }

    return 0;
}


#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100000 + 10;
const LL inf = (LL)(1e15);
int n,m,s,t,tot;
struct edges{
	int x,y,z;
	int useful,nec;
}e[N];
int h[N],adj[N * 2],nxt[N * 2],w[N * 2],dir[N * 2],id[N * 2],fa[N];
void addedge(int x,int y,int z,int flag){
	adj[++ tot] = y,nxt[tot] = h[x],w[tot] = z,dir[tot] = flag,h[x] = tot;
}
LL dist[N][2];
int iq[N],in[N];
queue<int>q;
void SPFA(int st,int flag){
	for (int i = 1;i <= n;i ++) dist[i][flag] = inf,iq[i] = 0;
	dist[st][flag] = 0,iq[st] = 1;
	while (!q.empty()) q.pop();
	q.push(st);
	while (!q.empty()){
		int u = q.front();
		for (int k = h[u];k;k = nxt[k])
			if (dir[k] == flag && dist[u][flag] + w[k] < dist[adj[k]][flag]){
				dist[adj[k]][flag] = dist[u][flag] + w[k];
				if (!iq[adj[k]]){
					iq[adj[k]] = 1;
					q.push(adj[k]);
				}
			}
		iq[u] = 0;
		q.pop();
	}
}
int dfn[N],low[N];
void dfs(int u){
	dfn[u] = low[u] = ++ tot;
	for (int k = h[u];k;k = nxt[k]){
		if (!dfn[adj[k]]){
			fa[adj[k]] = (k & 1) ? (k + 1) : (k - 1);
			dfs(adj[k]);
			low[u] = min(low[u],low[adj[k]]);
		}else{
			if (k != fa[u]) low[u] = min(low[u],dfn[adj[k]]);
		}
	}
	if (low[u] == dfn[u]){
		e[id[fa[u]]].nec = 1;
	}
}
void getbridge(){
	tot = 0;
	for (int i = 1;i <= n;i ++) dfn[i] = 0;
	for (int i = 1;i <= m;i ++)
		if (e[i].useful) e[i].nec = 0;
	dfs(1);
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i = 1;i <= n;i ++) h[i] = 0;
	tot = 0;
	for (int i = 1;i <= m;i ++){
		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
		addedge(e[i].x,e[i].y,e[i].z,1);
		addedge(e[i].y,e[i].x,e[i].z,0);
	}
	SPFA(s,1),SPFA(t,0);
	tot = 0;
	for (int i = 1;i <= n;i ++) h[i] = 0;
	for (int i = 1;i <= m;i ++){
		if (dist[e[i].x][1] + e[i].z + dist[e[i].y][0] > dist[t][1]){
			e[i].useful = 0;
		}else{
			e[i].useful = 1;
			addedge(e[i].x,e[i].y,e[i].z,1),id[tot] = i;
			addedge(e[i].y,e[i].x,e[i].z,0),id[tot] = i;
		}
	}
	getbridge();
	for (int i = 1;i <= m;i ++){
		if (e[i].useful){
			if (e[i].nec) puts("YES");
			else{
				if (e[i].z > 1) puts("CAN 1"); else puts("NO");
			}
		}else{
			LL more = dist[e[i].x][1] + e[i].z + dist[e[i].y][0] - dist[t][1];
			more ++;
			if (more < e[i].z) printf("CAN %d\n",(int)more); else puts("NO");
		}
	}
	return 0;
}


#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100000 + 10;
const LL inf = (LL)(1e15);
int n,m,s,t,tot;
struct edges{
	int x,y,z;
	int useful,nec;
}e[N];
int h[N],adj[N * 2],nxt[N * 2],w[N * 2],dir[N * 2],id[N * 2],fa[N];
void addedge(int x,int y,int z,int flag){
	adj[++ tot] = y,nxt[tot] = h[x],w[tot] = z,dir[tot] = flag,h[x] = tot;
}
LL dist[N][2];
int iq[N],in[N];
queue<int>q;
void SPFA(int st,int flag){
	for (int i = 1;i <= n;i ++) dist[i][flag] = inf,iq[i] = 0;
	dist[st][flag] = 0,iq[st] = 1;
	while (!q.empty()) q.pop();
	q.push(st);
	while (!q.empty()){
		int u = q.front();
		for (int k = h[u];k;k = nxt[k])
			if (dir[k] == flag && dist[u][flag] + w[k] < dist[adj[k]][flag]){
				dist[adj[k]][flag] = dist[u][flag] + w[k];
				if (!iq[adj[k]]){
					iq[adj[k]] = 1;
					q.push(adj[k]);
				}
			}
		iq[u] = 0;
		q.pop();
	}
}
int dfn[N],low[N];
void dfs(int u){
	dfn[u] = low[u] = ++ tot;
	for (int k = h[u];k;k = nxt[k]){
		if (k == fa[u]) continue;
		if (!dfn[adj[k]]){
			fa[adj[k]] = (k & 1) ? (k + 1) : (k - 1);
			dfs(adj[k]);
			low[u] = min(low[u],low[adj[k]]);
		}else{
			low[u] = min(low[u],dfn[adj[k]]);
		}
	}
	if (low[u] == dfn[u]){
		e[id[fa[u]]].nec = 1;
	}
}
void getbridge(){
	tot = 0;
	for (int i = 1;i <= n;i ++) dfn[i] = 0;
	for (int i = 1;i <= m;i ++)
		if (e[i].useful) e[i].nec = 0;
	dfs(1);
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i = 1;i <= n;i ++) h[i] = 0;
	tot = 0;
	for (int i = 1;i <= m;i ++){
		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
		addedge(e[i].x,e[i].y,e[i].z,1);
		addedge(e[i].y,e[i].x,e[i].z,0);
	}
	SPFA(s,1),SPFA(t,0);
	tot = 0;
	for (int i = 1;i <= n;i ++) h[i] = 0;
	for (int i = 1;i <= m;i ++){
		if (dist[e[i].x][1] + e[i].z + dist[e[i].y][0] > dist[t][1]){
			e[i].useful = 0;
		}else{
			e[i].useful = 1;
			addedge(e[i].x,e[i].y,e[i].z,1),id[tot] = i;
			addedge(e[i].y,e[i].x,e[i].z,0),id[tot] = i;
		}
	}
	getbridge();
	for (int i = 1;i <= m;i ++){
		if (e[i].useful){
			if (e[i].nec) puts("YES");
			else{
				if (e[i].z > 1) puts("CAN 1"); else puts("NO");
			}
		}else{
			LL more = dist[e[i].x][1] + e[i].z + dist[e[i].y][0] - dist[t][1];
			more ++;
			if (more < e[i].z) printf("CAN %d\n",(int)more); else puts("NO");
		}
	}
	return 0;
}


#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100000 + 10;
const LL inf = (LL)(1e15);
int n,m,s,t,tot;
struct edges{
	int x,y,z;
	int useful,nec;
}e[N];
int h[N],adj[N * 2],nxt[N * 2],w[N * 2],dir[N * 2],id[N * 2],fa[N];
void addedge(int x,int y,int z,int flag){
	adj[++ tot] = y,nxt[tot] = h[x],w[tot] = z,dir[tot] = flag,h[x] = tot;
}
LL dist[N][2];
int iq[N],in[N];
queue<int>q;
void SPFA(int st,int flag){
	for (int i = 1;i <= n;i ++) dist[i][flag] = inf,iq[i] = 0;
	dist[st][flag] = 0,iq[st] = 1;
	while (!q.empty()) q.pop();
	q.push(st);
	while (!q.empty()){
		int u = q.front();
		for (int k = h[u];k;k = nxt[k])
			if (dir[k] == flag && dist[u][flag] + w[k] < dist[adj[k]][flag]){
				dist[adj[k]][flag] = dist[u][flag] + w[k];
				if (!iq[adj[k]]){
					iq[adj[k]] = 1;
					q.push(adj[k]);
				}
			}
		iq[u] = 0;
		q.pop();
	}
}
int dfn[N],low[N];
void dfs(int u,int up){
	dfn[u] = low[u] = ++ tot;
	for (int k = h[u];k;k = nxt[k]){
		if (!dfn[adj[k]]){
			dfs(adj[k],(k & 1) ? (k + 1) : (k - 1));
			low[u] = min(low[u],low[adj[k]]);
			if (low[adj[k]] > dfn[u]){
				e[id[k]].nec = 1;
			}
		}else{
			if (k != up) low[u] = min(low[u],dfn[adj[k]]);
		}
	}
}
void getbridge(){
	tot = 0;
	dfs(1,0);
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i = 1;i <= n;i ++) h[i] = 0;
	tot = 0;
	for (int i = 1;i <= m;i ++){
		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
		addedge(e[i].x,e[i].y,e[i].z,1);
		addedge(e[i].y,e[i].x,e[i].z,0);
	}
	SPFA(s,1),SPFA(t,0);
	tot = 0;
	for (int i = 1;i <= n;i ++) h[i] = dfn[i] = 0;
	for (int i = 1;i <= m;i ++){
		if (dist[e[i].x][1] + e[i].z + dist[e[i].y][0] > dist[t][1]){
			e[i].useful = 0;
		}else{
			e[i].useful = 1;
			addedge(e[i].x,e[i].y,e[i].z,1),id[tot] = i;
			addedge(e[i].y,e[i].x,e[i].z,0),id[tot] = i;
			e[i].nec = 0;
		}
	}
	getbridge();
	for (int i = 1;i <= m;i ++){
		if (e[i].useful){
			if (e[i].nec) puts("YES");
			else{
				if (e[i].z > 1) puts("CAN 1"); else puts("NO");
			}
		}else{
			LL more = dist[e[i].x][1] + e[i].z + dist[e[i].y][0] - dist[t][1];
			more ++;
			if (more < e[i].z) printf("CAN %d\n",(int)more); else puts("NO");
		}
	}
	return 0;
}


#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100000 + 10;
const LL inf = (LL)(1e15);
int n,m,s,t,tot;
struct edges{
	int x,y,z;
	int useful,nec;
}e[N];
int h[N],adj[N * 2],nxt[N * 2],w[N * 2],dir[N * 2],id[N * 2],fa[N];
void addedge(int x,int y,int z,int flag){
	adj[++ tot] = y,nxt[tot] = h[x],w[tot] = z,dir[tot] = flag,h[x] = tot;
}
LL dist[N][2];
int iq[N],in[N];
queue<int>q;
void SPFA(int st,int flag){
	for (int i = 1;i <= n;i ++) dist[i][flag] = inf,iq[i] = 0;
	dist[st][flag] = 0,iq[st] = 1;
	while (!q.empty()) q.pop();
	q.push(st);
	while (!q.empty()){
		int u = q.front();
		for (int k = h[u];k;k = nxt[k])
			if (dir[k] == flag && dist[u][flag] + w[k] < dist[adj[k]][flag]){
				dist[adj[k]][flag] = dist[u][flag] + w[k];
				if (!iq[adj[k]]){
					iq[adj[k]] = 1;
					q.push(adj[k]);
				}
			}
		iq[u] = 0;
		q.pop();
	}
}
int dfn[N],low[N];
void dfs(int u){
	dfn[u] = low[u] = ++ tot;
	for (int k = h[u];k;k = nxt[k]){
		if (k == fa[u]) continue;
		if (!dfn[adj[k]]){
			fa[adj[k]] = (k & 1) ? (k + 1) : (k - 1);
			dfs(adj[k]);
			low[u] = min(low[u],low[adj[k]]);
			if (low[adj[k]] > dfn[u]){
				e[id[k]].nec = 1;
			}
		}else{
			low[u] = min(low[u],dfn[adj[k]]);
		}
	}
}
void getbridge(){
	tot = 0;
	for (int i = 1;i <= n;i ++) dfn[i] = 0;
	for (int i = 1;i <= m;i ++)
		if (e[i].useful) e[i].nec = 0;
	dfs(1);
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i = 1;i <= n;i ++) h[i] = 0;
	tot = 0;
	for (int i = 1;i <= m;i ++){
		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
		addedge(e[i].x,e[i].y,e[i].z,1);
		addedge(e[i].y,e[i].x,e[i].z,0);
	}
	SPFA(s,1),SPFA(t,0);
	tot = 0;
	for (int i = 1;i <= n;i ++) h[i] = 0;
	for (int i = 1;i <= m;i ++){
		if (dist[e[i].x][1] + e[i].z + dist[e[i].y][0] > dist[t][1]){
			e[i].useful = 0;
		}else{
			e[i].useful = 1;
			addedge(e[i].x,e[i].y,e[i].z,1),id[tot] = i;
			addedge(e[i].y,e[i].x,e[i].z,0),id[tot] = i;
		}
	}
	getbridge();
	for (int i = 1;i <= m;i ++){
		if (e[i].useful){
			if (e[i].nec) puts("YES");
			else{
				if (e[i].z > 1) puts("CAN 1"); else puts("NO");
			}
		}else{
			LL more = dist[e[i].x][1] + e[i].z + dist[e[i].y][0] - dist[t][1];
			more ++;
			if (more < e[i].z) printf("CAN %d\n",(int)more); else puts("NO");
		}
	}
	return 0;
}


#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100000 + 10;
const LL inf = (LL)(1e15);
int n,m,s,t,tot;
struct edges{
	int x,y,z;
	int useful,nec;
}e[N];
int h[N],adj[N * 2],nxt[N * 2],w[N * 2],dir[N * 2],id[N * 2],fa[N];
void addedge(int x,int y,int z,int flag){
	adj[++ tot] = y,nxt[tot] = h[x],w[tot] = z,dir[tot] = flag,h[x] = tot;
}
LL dist[N][2];
int iq[N],in[N];
queue<int>q;
void SPFA(int st,int flag){
	for (int i = 1;i <= n;i ++) dist[i][flag] = inf,iq[i] = 0;
	dist[st][flag] = 0,iq[st] = 1;
	while (!q.empty()) q.pop();
	q.push(st);
	while (!q.empty()){
		int u = q.front();
		for (int k = h[u];k;k = nxt[k])
			if (dir[k] == flag && dist[u][flag] + w[k] < dist[adj[k]][flag]){
				dist[adj[k]][flag] = dist[u][flag] + w[k];
				if (!iq[adj[k]]){
					iq[adj[k]] = 1;
					q.push(adj[k]);
				}
			}
		iq[u] = 0;
		q.pop();
	}
}
int dfn[N],low[N];
void dfs(int u){
	dfn[u] = low[u] = ++ tot;
	for (int k = h[u];k;k = nxt[k]){
		if (!dfn[adj[k]]){
			if (k % 2 == 1) fa[adj[k]] = k + 1; else fa[adj[k]] = k - 1;
			dfs(adj[k]);
			low[u] = min(low[u],low[adj[k]]);
		}else{
			if (k != fa[u]) low[u] = min(low[u],dfn[adj[k]]);
		}
	}
	if (fa[u] && low[u] == dfn[u]){
		e[id[fa[u]]].nec = 1;
	}
}
void getbridge(){
	tot = 0;
	dfs(1);
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i = 1;i <= n;i ++) h[i] = 0;
	tot = 0;
	for (int i = 1;i <= m;i ++){
		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
		addedge(e[i].x,e[i].y,e[i].z,1);
		addedge(e[i].y,e[i].x,e[i].z,0);
	}
	SPFA(s,1),SPFA(t,0);
	tot = 0;
	for (int i = 1;i <= n;i ++) h[i] = dfn[i] = 0;
	for (int i = 1;i <= m;i ++){
		if (dist[e[i].x][1] + e[i].z + dist[e[i].y][0] > dist[t][1]){
			e[i].useful = 0;
		}else{
			e[i].useful = 1;
			addedge(e[i].x,e[i].y,e[i].z,1),id[tot] = i;
			addedge(e[i].y,e[i].x,e[i].z,0),id[tot] = i;
			e[i].nec = 0;
		}
	}
	getbridge();
	for (int i = 1;i <= m;i ++){
		if (e[i].useful){
			if (e[i].nec) puts("YES");
			else{
				if (e[i].z > 1) puts("CAN 1"); else puts("NO");
			}
		}else{
			LL more = dist[e[i].x][1] + e[i].z + dist[e[i].y][0] - dist[t][1];
			more ++;
			if (more < e[i].z) printf("CAN %d\n",(int)more); else puts("NO");
		}
	}
	return 0;
}


#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100000 + 10;
const LL inf = (LL)(1e15);
int n,m,s,t,tot;
struct edges{
	int x,y,z;
	int useful,nec;
}e[N];
int h[N],adj[N * 2],nxt[N * 2],w[N * 2],dir[N * 2],id[N * 2],fa[N];
void addedge(int x,int y,int z,int flag){
	adj[++ tot] = y,nxt[tot] = h[x],w[tot] = z,dir[tot] = flag,h[x] = tot;
}
LL dist[N][2];
int iq[N],in[N];
queue<int>q;
void SPFA(int st,int flag){
	for (int i = 1;i <= n;i ++) dist[i][flag] = inf,iq[i] = 0;
	dist[st][flag] = 0,iq[st] = 1;
	while (!q.empty()) q.pop();
	q.push(st);
	while (!q.empty()){
		int u = q.front();
		for (int k = h[u];k;k = nxt[k])
			if (dir[k] == flag && dist[u][flag] + w[k] < dist[adj[k]][flag]){
				dist[adj[k]][flag] = dist[u][flag] + w[k];
				if (!iq[adj[k]]){
					iq[adj[k]] = 1;
					q.push(adj[k]);
				}
			}
		iq[u] = 0;
		q.pop();
	}
}
int dfn[N],low[N];
void dfs(int u,int up){
	dfn[u] = low[u] = ++ tot;
	for (int k = h[u];k;k = nxt[k]){
		if (!dfn[adj[k]]){
			dfs(adj[k],(k & 1) ? (k + 1) : (k - 1));
			low[u] = min(low[u],low[adj[k]]);
			if (n == 100 && m == 150 && s == 79 && t == 67 && (u == 19 || u == 6) && (adj[k] == 19 || adj[k] == 6)){
				printf("%d %d\n",dfn[u],low[adj[k]]);
			}
			if (low[adj[k]] > dfn[u]){
				e[id[k]].nec = 1;
			}
		}else{
			if (k != up) low[u] = min(low[u],dfn[adj[k]]);
		}
	}
}
void getbridge(){
	tot = 0;
	dfs(1,0);
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i = 1;i <= n;i ++) h[i] = 0;
	tot = 0;
	for (int i = 1;i <= m;i ++){
		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
		addedge(e[i].x,e[i].y,e[i].z,1);
		addedge(e[i].y,e[i].x,e[i].z,0);
	}
	SPFA(s,1),SPFA(t,0);
	tot = 0;
	for (int i = 1;i <= n;i ++) h[i] = dfn[i] = 0;
	for (int i = 1;i <= m;i ++){
		if (dist[e[i].x][1] + e[i].z + dist[e[i].y][0] > dist[t][1]){
			e[i].useful = 0;
		}else{
			e[i].useful = 1;
			addedge(e[i].x,e[i].y,e[i].z,1),id[tot] = i;
			addedge(e[i].y,e[i].x,e[i].z,0),id[tot] = i;
			e[i].nec = 0;
		}
	}
	getbridge();
	for (int i = 1;i <= m;i ++){
		if (e[i].useful){
			if (e[i].nec) puts("YES");
			else{
				if (e[i].z > 1) puts("CAN 1"); else puts("NO");
			}
		}else{
			LL more = dist[e[i].x][1] + e[i].z + dist[e[i].y][0] - dist[t][1];
			more ++;
			if (more < e[i].z) printf("CAN %d\n",(int)more); else puts("NO");
		}
	}
	return 0;
}


#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100000 + 10;
const LL inf = (LL)(1e15);
int n,m,s,t,tot;
struct edges{
	int x,y,z;
	int useful,nec;
}e[N];
int h[N],adj[N * 2],nxt[N * 2],w[N * 2],dir[N * 2],id[N * 2],fa[N];
void addedge(int x,int y,int z,int flag){
	adj[++ tot] = y,nxt[tot] = h[x],w[tot] = z,dir[tot] = flag,h[x] = tot;
}
LL dist[N][2];
int iq[N],in[N];
queue<int>q;
void SPFA(int st,int flag){
	for (int i = 1;i <= n;i ++) dist[i][flag] = inf,iq[i] = 0;
	dist[st][flag] = 0,iq[st] = 1;
	while (!q.empty()) q.pop();
	q.push(st);
	while (!q.empty()){
		int u = q.front();
		for (int k = h[u];k;k = nxt[k])
			if (dir[k] == flag && dist[u][flag] + w[k] < dist[adj[k]][flag]){
				dist[adj[k]][flag] = dist[u][flag] + w[k];
				if (!iq[adj[k]]){
					iq[adj[k]] = 1;
					q.push(adj[k]);
				}
			}
		iq[u] = 0;
		q.pop();
	}
}
int dfn[N],low[N];
void dfs(int u,int up){
	dfn[u] = low[u] = ++ tot;
	for (int k = h[u];k;k = nxt[k]){
		if (n == 100 && m == 150 && s == 79 && t == 67 && (u == 19 || u == 6) && (adj[k] == 19 || adj[k] == 6)){
				printf("%d\n",dfn[adj[k]]);
		}
		if (!dfn[adj[k]]){
			dfs(adj[k],(k & 1) ? (k + 1) : (k - 1));
			low[u] = min(low[u],low[adj[k]]);
			if (low[adj[k]] > dfn[u]){
				e[id[k]].nec = 1;
			}
		}else{
			if (k != up) low[u] = min(low[u],dfn[adj[k]]);
		}
	}
}
void getbridge(){
	tot = 0;
	dfs(1,0);
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i = 1;i <= n;i ++) h[i] = 0;
	tot = 0;
	for (int i = 1;i <= m;i ++){
		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
		addedge(e[i].x,e[i].y,e[i].z,1);
		addedge(e[i].y,e[i].x,e[i].z,0);
	}
	SPFA(s,1),SPFA(t,0);
	tot = 0;
	for (int i = 1;i <= n;i ++) h[i] = dfn[i] = 0;
	for (int i = 1;i <= m;i ++){
		if (dist[e[i].x][1] + e[i].z + dist[e[i].y][0] > dist[t][1]){
			e[i].useful = 0;
		}else{
			e[i].useful = 1;
			addedge(e[i].x,e[i].y,e[i].z,1),id[tot] = i;
			addedge(e[i].y,e[i].x,e[i].z,0),id[tot] = i;
			e[i].nec = 0;
		}
	}
	getbridge();
	for (int i = 1;i <= m;i ++){
		if (e[i].useful){
			if (e[i].nec) puts("YES");
			else{
				if (e[i].z > 1) puts("CAN 1"); else puts("NO");
			}
		}else{
			LL more = dist[e[i].x][1] + e[i].z + dist[e[i].y][0] - dist[t][1];
			more ++;
			if (more < e[i].z) printf("CAN %d\n",(int)more); else puts("NO");
		}
	}
	return 0;
}


#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100000 + 10;
const LL inf = (LL)(1e15);
int n,m,s,t,tot;
struct edges{
	int x,y,z;
	int useful,nec;
}e[N];
int h[N],adj[N * 2],nxt[N * 2],w[N * 2],dir[N * 2],id[N * 2],fa[N];
void addedge(int x,int y,int z,int flag){
	adj[++ tot] = y,nxt[tot] = h[x],w[tot] = z,dir[tot] = flag,h[x] = tot;
}
LL dist[N][2];
int iq[N],in[N];
queue<int>q;
void SPFA(int st,int flag){
	for (int i = 1;i <= n;i ++) dist[i][flag] = inf,iq[i] = 0;
	dist[st][flag] = 0,iq[st] = 1;
	while (!q.empty()) q.pop();
	q.push(st);
	while (!q.empty()){
		int u = q.front();
		for (int k = h[u];k;k = nxt[k])
			if (dir[k] == flag && dist[u][flag] + w[k] < dist[adj[k]][flag]){
				dist[adj[k]][flag] = dist[u][flag] + w[k];
				if (!iq[adj[k]]){
					iq[adj[k]] = 1;
					q.push(adj[k]);
				}
			}
		iq[u] = 0;
		q.pop();
	}
}
int dfn[N],low[N];
void dfs(int u,int up){
	dfn[u] = low[u] = ++ tot;
	for (int k = h[u];k;k = nxt[k]){
		if (!dfn[adj[k]]){
			dfs(adj[k],(k & 1) ? (k + 1) : (k - 1));
			low[u] = min(low[u],low[adj[k]]);
			if (n == 100 && m == 150 && s == 79 && t == 67 && (u == 73 || u == 71) && (adj[k] == 73 || adj[k] == 71)){
				printf("%d %d\n",dfn[u],low[adj[k]]);
			}
			if (low[adj[k]] > dfn[u]){
				e[id[k]].nec = 1;
			}
		}else{
			if (k != up) low[u] = min(low[u],dfn[adj[k]]);
		}
	}
}
void getbridge(){
	tot = 0;
	dfs(1,0);
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i = 1;i <= n;i ++) h[i] = 0;
	tot = 0;
	for (int i = 1;i <= m;i ++){
		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
		addedge(e[i].x,e[i].y,e[i].z,1);
		addedge(e[i].y,e[i].x,e[i].z,0);
	}
	SPFA(s,1),SPFA(t,0);
	tot = 0;
	for (int i = 1;i <= n;i ++) h[i] = dfn[i] = 0;
	for (int i = 1;i <= m;i ++){
		if (dist[e[i].x][1] + e[i].z + dist[e[i].y][0] > dist[t][1]){
			e[i].useful = 0;
		}else{
			e[i].useful = 1;
			addedge(e[i].x,e[i].y,e[i].z,1),id[tot] = i;
			addedge(e[i].y,e[i].x,e[i].z,0),id[tot] = i;
			e[i].nec = 0;
		}
	}
	getbridge();
	for (int i = 1;i <= m;i ++){
		if (e[i].useful){
			if (e[i].nec) puts("YES");
			else{
				if (e[i].z > 1) puts("CAN 1"); else puts("NO");
			}
		}else{
			LL more = dist[e[i].x][1] + e[i].z + dist[e[i].y][0] - dist[t][1];
			more ++;
			if (more < e[i].z) printf("CAN %d\n",(int)more); else puts("NO");
		}
	}
	return 0;
}


#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100000 + 10;
const LL inf = (LL)(1e15);
int n,m,s,t,tot;
struct edges{
	int x,y,z;
	int useful,nec;
}e[N];
int h[N],adj[N * 2],nxt[N * 2],w[N * 2],dir[N * 2],id[N * 2],fa[N];
void addedge(int x,int y,int z,int flag){
	adj[++ tot] = y,nxt[tot] = h[x],w[tot] = z,dir[tot] = flag,h[x] = tot;
}
LL dist[N][2];
int iq[N],in[N];
queue<int>q;
void SPFA(int st,int flag){
	for (int i = 1;i <= n;i ++) dist[i][flag] = inf,iq[i] = 0;
	dist[st][flag] = 0,iq[st] = 1;
	while (!q.empty()) q.pop();
	q.push(st);
	while (!q.empty()){
		int u = q.front();
		for (int k = h[u];k;k = nxt[k])
			if (dir[k] == flag && dist[u][flag] + w[k] < dist[adj[k]][flag]){
				dist[adj[k]][flag] = dist[u][flag] + w[k];
				if (!iq[adj[k]]){
					iq[adj[k]] = 1;
					q.push(adj[k]);
				}
			}
		iq[u] = 0;
		q.pop();
	}
}
int dfn[N],low[N];
void dfs(int u,int up){
	dfn[u] = low[u] = ++ tot;
	for (int k = h[u];k;k = nxt[k]){
		/*
		if (n == 100 && m == 150 && s == 79 && t == 67 && (u == 19 || u == 6) && (adj[k] == 19 || adj[k] == 6)){
				printf("%d\n",dfn[adj[k]]);
		}
		*/
		if (!dfn[adj[k]]){
			dfs(adj[k],(k & 1) ? (k + 1) : (k - 1));
			low[u] = min(low[u],low[adj[k]]);
			if (low[adj[k]] > dfn[u]){
				e[id[k]].nec = 1;
			}
		}else{
			if (k != up) low[u] = min(low[u],dfn[adj[k]]);
		}
	}
}
void getbridge(){
	tot = 0;
	dfs(s,0);
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i = 1;i <= n;i ++) h[i] = 0;
	tot = 0;
	for (int i = 1;i <= m;i ++){
		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
		addedge(e[i].x,e[i].y,e[i].z,1);
		addedge(e[i].y,e[i].x,e[i].z,0);
	}
	SPFA(s,1),SPFA(t,0);
	tot = 0;
	for (int i = 1;i <= n;i ++) h[i] = dfn[i] = 0;
	for (int i = 1;i <= m;i ++){
		if (dist[e[i].x][1] + e[i].z + dist[e[i].y][0] > dist[t][1]){
			e[i].useful = 0;
		}else{
			e[i].useful = 1;
			addedge(e[i].x,e[i].y,e[i].z,1),id[tot] = i;
			addedge(e[i].y,e[i].x,e[i].z,0),id[tot] = i;
			e[i].nec = 0;
		}
	}
	getbridge();
	for (int i = 1;i <= m;i ++){
		if (e[i].useful){
			if (e[i].nec) puts("YES");
			else{
				if (e[i].z > 1) puts("CAN 1"); else puts("NO");
			}
		}else{
			LL more = dist[e[i].x][1] + e[i].z + dist[e[i].y][0] - dist[t][1];
			more ++;
			if (more < e[i].z) printf("CAN %d\n",(int)more); else puts("NO");
		}
	}
	return 0;
}


#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100000 + 10;
const LL inf = (LL)(1e15);
int n,m,s,t,tot;
struct edges{
	int x,y,z;
	int useful,nec;
}e[N];
int h[N],adj[N * 2],nxt[N * 2],w[N * 2],dir[N * 2],id[N * 2],fa[N];
void addedge(int x,int y,int z,int flag){
	adj[++ tot] = y,nxt[tot] = h[x],w[tot] = z,dir[tot] = flag,h[x] = tot;
}
LL dist[N][2];
int iq[N],in[N];
queue<int>q;
void SPFA(int st,int flag){
	for (int i = 1;i <= n;i ++) dist[i][flag] = inf,iq[i] = 0;
	dist[st][flag] = 0,iq[st] = 1;
	while (!q.empty()) q.pop();
	q.push(st);
	while (!q.empty()){
		int u = q.front();
		for (int k = h[u];k;k = nxt[k])
			if (dir[k] == flag && dist[u][flag] + w[k] < dist[adj[k]][flag]){
				dist[adj[k]][flag] = dist[u][flag] + w[k];
				if (!iq[adj[k]]){
					iq[adj[k]] = 1;
					q.push(adj[k]);
				}
			}
		iq[u] = 0;
		q.pop();
	}
}
int dfn[N],low[N];
void dfs(int u,int up){
	dfn[u] = low[u] = ++ tot;
	for (int k = h[u];k;k = nxt[k]){
		if (!dfn[adj[k]]){
			dfs(adj[k],(k & 1) ? (k + 1) : (k - 1));
			low[u] = min(low[u],low[adj[k]]);
			if (n == 100 && m == 150 && s == 79 && t == 67 && (u == 19 || u == 6) && (adj[k] == 19 || adj[k] == 6)){
				printf("%d %d\n",dfn[u],low[adj[k]]);
			}
			if (low[adj[k]] > dfn[u]){
				e[id[k]].nec = 1;
			}
		}else{
			if (k != up) low[u] = min(low[u],dfn[adj[k]]);
		}
	}
}
void getbridge(){
	tot = 0;
	dfs(1,0);
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i = 1;i <= n;i ++) h[i] = 0;
	tot = 0;
	for (int i = 1;i <= m;i ++){
		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
		addedge(e[i].x,e[i].y,e[i].z,1);
		addedge(e[i].y,e[i].x,e[i].z,0);
	}
	SPFA(s,1),SPFA(t,0);
	tot = 0;
	for (int i = 1;i <= n;i ++) h[i] = dfn[i] = 0;
	for (int i = 1;i <= m;i ++){
		if (dist[e[i].x][1] + e[i].z + dist[e[i].y][0] > dist[t][1]){
			e[i].useful = 0;
		}else{
			e[i].useful = 1;
			addedge(e[i].x,e[i].y,e[i].z,1),id[tot] = i;
			addedge(e[i].y,e[i].x,e[i].z,0),id[tot] = i;
			e[i].nec = 0;
		}
		if (n == 100 && m == 150 && s == 79 && t == 67 && e[i].x == 19 && e[i].y == 6 && e[i].z == 2425){
			printf("%d\n",e[i].useful);
		}
	}
	getbridge();
	for (int i = 1;i <= m;i ++){
		if (e[i].useful){
			if (e[i].nec) puts("YES");
			else{
				if (e[i].z > 1) puts("CAN 1"); else puts("NO");
			}
		}else{
			LL more = dist[e[i].x][1] + e[i].z + dist[e[i].y][0] - dist[t][1];
			more ++;
			if (more < e[i].z) printf("CAN %d\n",(int)more); else puts("NO");
		}
	}
	return 0;
}


#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100000 + 10;
const LL inf = (LL)(1e15);
int n,m,s,t,tot;
struct edges{
	int x,y,z;
	int useful,nec;
}e[N];
int h[N],adj[N * 2],nxt[N * 2],w[N * 2],dir[N * 2],id[N * 2],use[N * 2];
void addedge(int x,int y,int z,int flag){
	adj[++ tot] = y,nxt[tot] = h[x],w[tot] = z,dir[tot] = flag,h[x] = tot;
}
LL dist[N][2];
int iq[N],in[N];
queue<int>q;
void SPFA(int st,int flag){
	for (int i = 1;i <= n;i ++) dist[i][flag] = inf,iq[i] = 0;
	dist[st][flag] = 0,iq[st] = 1;
	while (!q.empty()) q.pop();
	q.push(st);
	while (!q.empty()){
		int u = q.front();
		for (int k = h[u];k;k = nxt[k])
			if (dir[k] == flag && dist[u][flag] + w[k] < dist[adj[k]][flag]){
				dist[adj[k]][flag] = dist[u][flag] + w[k];
				if (!iq[adj[k]]){
					iq[adj[k]] = 1;
					q.push(adj[k]);
				}
			}
		iq[u] = 0;
		q.pop();
	}
}
int dfn[N],low[N];
void dfs(int u){
	dfn[u] = low[u] = ++ tot;
	for (int k = h[u];k;k = nxt[k]){
		if (use[k]) continue;
		if (!dfn[adj[k]]){
			use[(k & 1) ? (k + 1) : (k - 1)] = 1;
			dfs(adj[k]);
			low[u] = min(low[u],low[adj[k]]);
			if (low[adj[k]] > dfn[u]){
				e[id[k]].nec = 1;
				//printf("%d %d\n",u,adj[k]);
			}
		}else{
			low[u] = min(low[u],dfn[adj[k]]);
		}
	}
}
void getbridge(){
	tot = 0;
	for (int i = 1;i <= n;i ++) dfn[i] = 0;
	for (int i = 1;i <= m;i ++)
		if (e[i].useful) e[i].nec = 0;
	dfs(1);
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i = 1;i <= n;i ++) h[i] = 0;
	tot = 0;
	for (int i = 1;i <= m;i ++){
		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
		addedge(e[i].x,e[i].y,e[i].z,1);
		addedge(e[i].y,e[i].x,e[i].z,0);
	}
	SPFA(s,1),SPFA(t,0);
	tot = 0;
	for (int i = 1;i <= n;i ++) h[i] = 0;
	for (int i = 1;i <= m;i ++){
		if (dist[e[i].x][1] + e[i].z + dist[e[i].y][0] > dist[t][1]){
			e[i].useful = 0;
		}else{
			e[i].useful = 1;
			addedge(e[i].x,e[i].y,e[i].z,1),id[tot] = i,use[tot] = 0;
			addedge(e[i].y,e[i].x,e[i].z,0),id[tot] = i,use[tot] = 0;
		}
	}
	getbridge();
	for (int i = 1;i <= m;i ++){
		if (e[i].useful){
			if (e[i].nec) puts("YES");
			else{
				if (e[i].z > 1) puts("CAN 1"); else puts("NO");
			}
		}else{
			LL more = dist[e[i].x][1] + e[i].z + dist[e[i].y][0] - dist[t][1];
			more ++;
			if (more < e[i].z) printf("CAN %d\n",(int)more); else puts("NO");
		}
	}
	return 0;
}


#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100000 + 10;
const LL inf = (LL)(1e15);
int n,m,s,t,tot;
struct edges{
	int x,y,z;
	int useful,nec;
}e[N];
int h[N],adj[N * 2],nxt[N * 2],w[N * 2],dir[N * 2];
void addedge(int x,int y,int z,int flag){
	adj[++ tot] = y,nxt[tot] = h[x],w[tot] = z,dir[tot] = flag,h[x] = tot;
}
LL dist[N][2],way[N][2];
int iq[N],in[N];
queue<int>q;
void SPFA(int st,int flag){
	for (int i = 1;i <= n;i ++) dist[i][flag] = inf,iq[i] = 0;
	dist[st][flag] = 0,iq[st] = 1;
	while (!q.empty()) q.pop();
	q.push(st);
	while (!q.empty()){
		int u = q.front();
		for (int k = h[u];k;k = nxt[k])
			if (dir[k] == flag && dist[u][flag] + w[k] < dist[adj[k]][flag]){
				dist[adj[k]][flag] = dist[u][flag] + w[k];
				if (!iq[adj[k]]){
					iq[adj[k]] = 1;
					q.push(adj[k]);
				}
			}
		iq[u] = 0;
		q.pop();
	}
}
void walk(int st,int flag){
	while (!q.empty()) q.pop();
	for (int i = 1;i <= n;i ++) way[i][flag] = 0;
	q.push(st),way[st][flag] = 1;
	while (!q.empty()){
		int u = q.front();
		for (int k = h[u];k;k = nxt[k]){
			if (dir[k] == flag){
				way[adj[k]][flag] += way[u][flag];
				-- in[adj[k]];
				if (in[adj[k]] == 0){
					q.push(adj[k]);
				}
			}
		}
		q.pop();
	}
}
void getway(){
	for (int i = 1;i <= n;i ++) in[i] = 0;
	for (int i = 1;i <= m;i ++){
		if (e[i].useful) in[e[i].y] ++;
	}
	walk(s,1);
	for (int i = 1;i <= n;i ++) in[i] = 0;
	for (int i = 1;i <= m;i ++){
		if (e[i].useful) in[e[i].x] ++;
	}
	walk(t,0);
}
void getnec(){
	for (int i = 1;i <= m;i ++){
		if (e[i].useful){
			if (way[e[i].x][1] * way[e[i].y][0] == way[t][1]) e[i].nec = 1;
			else e[i].nec = 0;
		}
	}
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i = 1;i <= n;i ++) h[i] = 0;
	tot = 0;
	for (int i = 1;i <= m;i ++){
		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
		addedge(e[i].x,e[i].y,e[i].z,1);
		addedge(e[i].y,e[i].x,e[i].z,0);
	}
	SPFA(s,1),SPFA(t,0);
	tot = 0;
	for (int i = 1;i <= n;i ++) h[i] = 0;
	for (int i = 1;i <= m;i ++){
		if (dist[e[i].x][1] + e[i].z + dist[e[i].y][0] > dist[t][1]){
			e[i].useful = 0;
		}else{
			e[i].useful = 1;
			addedge(e[i].x,e[i].y,e[i].z,1);
			addedge(e[i].y,e[i].x,e[i].z,0);
		}
	}
	getway();
	getnec();
	for (int i = 1;i <= m;i ++){
		if (e[i].useful){
			if (e[i].nec) puts("YES");
			else{
				if (e[i].z > 1) puts("CAN 1"); else puts("NO");
			}
		}else{
			LL more = dist[e[i].x][1] + e[i].z + dist[e[i].y][0] - dist[t][1];
			more ++;
			if (more < e[i].z) printf("CAN %d\n",(int)more); else puts("NO");
		}
	}
	return 0;
}


#include<cstdio>
#include<queue>
#include<algorithm>
#define X first
#define Y second
#define mp make_pair
using namespace std;
typedef long long LL;
const int N = 100000 + 10;
const LL inf = (LL)(1e15);
int n,m,s,t,tot;
struct edges{
	int x,y,z;
	int useful,nec;
}e[N];
int h[N],adj[N * 2],nxt[N * 2],w[N * 2],dir[N * 2],id[N * 2],fa[N];
void addedge(int x,int y,int z,int flag){
	adj[++ tot] = y,nxt[tot] = h[x],w[tot] = z,dir[tot] = flag,h[x] = tot;
}
LL dist[N][2];
int iq[N];
queue<int>q;
priority_queue<pair<LL,int> >Q;
void Dijkstra(int st,int flag){
	while (!Q.empty()) Q.pop();
	for (int i = 1;i <= n;i ++) {
		dist[i][flag] = inf;
		if (i != st) Q.push(mp(-inf,i));
	}
	int u,v;
	dist[st][flag] = 0;
	Q.push(mp(0,st));
	for (int i = 1;i < n;i ++){
		while (dist[Q.top().Y][flag] != -Q.top().X) Q.pop();
		u = Q.top().Y,Q.pop();
		for (int k = h[u];k;k = nxt[k]){
			if (dir[k] == flag && dist[u][flag] + w[k] < dist[adj[k]][flag]){
				dist[adj[k]][flag] = dist[u][flag] + w[k];
				Q.push(mp(-dist[adj[k]][flag],adj[k]));
			}
		}
	}
}
int dfn[N],low[N];
void dfs(int u,int up){
	dfn[u] = low[u] = ++ tot;
	for (int k = h[u];k;k = nxt[k]){
		if (!dfn[adj[k]]){
			dfs(adj[k],(k & 1) ? (k + 1) : (k - 1));
			low[u] = min(low[u],low[adj[k]]);
			if (low[adj[k]] > dfn[u]){
				e[id[k]].nec = 1;
			}
		}else{
			if (k != up) low[u] = min(low[u],dfn[adj[k]]);
		}
	}
}
void getbridge(){
	tot = 0;
	dfs(s,0);
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i = 1;i <= n;i ++) h[i] = 0;
	tot = 0;
	for (int i = 1;i <= m;i ++){
		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
		addedge(e[i].x,e[i].y,e[i].z,1);
		addedge(e[i].y,e[i].x,e[i].z,0);
	}
	Dijkstra(s,1),Dijkstra(t,0);
	tot = 0;
	for (int i = 1;i <= n;i ++) h[i] = dfn[i] = 0;
	for (int i = 1;i <= m;i ++){
		if (dist[e[i].x][1] + e[i].z + dist[e[i].y][0] > dist[t][1]){
			e[i].useful = 0;
		}else{
			e[i].useful = 1;
			addedge(e[i].x,e[i].y,e[i].z,1),id[tot] = i;
			addedge(e[i].y,e[i].x,e[i].z,0),id[tot] = i;
			e[i].nec = 0;
		}
	}
	getbridge();
	for (int i = 1;i <= m;i ++){
		if (e[i].useful){
			if (e[i].nec) puts("YES");
			else{
				if (e[i].z > 1) puts("CAN 1"); else puts("NO");
			}
		}else{
			LL more = dist[e[i].x][1] + e[i].z + dist[e[i].y][0] - dist[t][1];
			more ++;
			if (more < e[i].z) printf("CAN %d\n",(int)more); else puts("NO");
		}
	}
	return 0;
}


#include <stdio.h>
#include <vector>
#include <algorithm>
#define nmax 100010

using namespace std;
typedef long long int ll;

struct edge { int x,y,cost; };

int n,m,s,t,nr,x,y,z;
int heap[nmax],pos[nmax],frd[nmax],fr[nmax];
int dad[nmax],niv[nmax],livmin[nmax],mindist;
ll ds[nmax],dt[nmax],d[nmax];
edge e[nmax];
vector < pair <int,int> > g[nmax],gt[nmax],gc[nmax];

void Swap(int &x,int &y)
{
    swap(x,y); swap(pos[x],pos[y]);
}

void heapup(int v)
{
    int k=heap[v];
    while (v>1 && d[heap[v]]<d[heap[v/2]]) {
        Swap(heap[v],heap[v/2]); v=v/2;
    }
    heap[v]=k;
}

void heapdown(int v)
{
    int w=v*2;
    while (w<=nr) {
        if (w+1<=nr && d[heap[w]]>d[heap[w+1]]) w++;
        if (d[heap[v]]>d[heap[w]]) Swap(heap[v],heap[w]); else break;
        v=w; w=w*2;
    }
}

void delete_heap()
{
    Swap(heap[1],heap[nr]); nr--; heapdown(1);
}

void dfs(int nod,int ind)
{
    fr[nod]=1; livmin[nod]=niv[nod];

    for (int i=0;i<(int)gc[nod].size();i++)
        if (fr[gc[nod][i].first]==0) {
            niv[gc[nod][i].first]=niv[nod]+1;
            dad[gc[nod][i].first]=nod;
            dfs(gc[nod][i].first,gc[nod][i].second);
            livmin[nod]=min(livmin[nod],livmin[gc[nod][i].first]);
            if (livmin[gc[nod][i].first]>niv[nod]) frd[gc[nod][i].second]=1;
        } else
        if (gc[nod][i].second!=ind) livmin[nod]=min(livmin[nod],niv[gc[nod][i].first]);

}

int main()
{
    //freopen("1.in","r",stdin);

    scanf("%d %d %d %d",&n,&m,&s,&t);

    for (int i=1;i<=m;i++) {
        scanf("%d %d %d",&x,&y,&z); e[i]={x,y,z};
        g[x].push_back(make_pair(y,z));
        gt[y].push_back(make_pair(x,z));
    }

    for (int i=1;i<=n;i++) {
        d[i]=1e18; heap[i]=i; pos[i]=i;
    }

    d[s]=0; heapup(pos[s]); nr=n;

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)g[x].size();i++)
            if (d[x]+g[x][i].second<d[g[x][i].first]) {
                d[g[x][i].first]=d[x]+g[x][i].second; heapup(pos[g[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) ds[i]=d[i];

    for (int i=1;i<=n;i++) {
        d[i]=1e18; heap[i]=i; pos[i]=i;
    }

    d[t]=0; heapup(pos[t]); nr=n; mindist=ds[t];

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)gt[x].size();i++)
            if (d[x]+gt[x][i].second<d[gt[x][i].first]) {
                d[gt[x][i].first]=d[x]+gt[x][i].second; heapup(pos[gt[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) dt[i]=d[i];

    for (int i=1;i<=m;i++) {
        int x=e[i].x,y=e[i].y;
        if (ds[x]+e[i].cost+dt[y]==mindist)
            gc[x].push_back(make_pair(y,i)),gc[y].push_back(make_pair(x,i));
    }

    dfs(s,-1);

    for (int i=1;i<=m;i++)
        if (frd[i]==1) puts("YES"); else {
            int x=e[i].x,y=e[i].y,cost=e[i].cost;
            if (ds[x]==1e18 || dt[y]==1e18 || mindist-ds[x]-dt[y]-1<=0 || cost<=(mindist-ds[x]-dt[y]-1)) puts("NO"); else
                printf("CAN %d\n",cost-(mindist-ds[x]-dt[y]-1));
        }

    return 0;
}


#include <stdio.h>
#include <vector>
#include <algorithm>
#define nmax 100010

using namespace std;

struct edge { int x,y,cost; };

int n,m,s,t,nr,x,y,z,mindist;
int heap[nmax],pos[nmax],d[nmax],path[nmax];
int ds[nmax],dt[nmax],frd[nmax],fr[nmax];
int dad[nmax],niv[nmax],livmin[nmax];
edge e[nmax];
vector < pair <int,int> > g[nmax],gt[nmax],gc[nmax];

void Swap(int &x,int &y)
{
    swap(x,y); swap(pos[x],pos[y]);
}

void heapup(int v)
{
    int k=heap[v];
    while (v>1 && d[heap[v]]<d[heap[v/2]]) {
        Swap(heap[v],heap[v/2]); v=v/2;
    }
    heap[v]=k;
}

void heapdown(int v)
{
    int w=v*2;
    while (w<=nr) {
        if (w+1<=nr && d[heap[w]]>d[heap[w+1]]) w++;
        if (d[heap[v]]>d[heap[w]]) Swap(heap[v],heap[w]); else break;
        v=w; w=w*2;
    }
}

void delete_heap()
{
    Swap(heap[1],heap[nr]); nr--; heapdown(1);
}

void dfs(int nod)
{
    fr[nod]=1; livmin[nod]=niv[nod];

    for (int i=0;i<(int)gc[nod].size();i++)
        if (fr[gc[nod][i].first]==0) {
            niv[gc[nod][i].first]=niv[nod]+1;
            dad[gc[nod][i].first]=nod;
            dfs(gc[nod][i].first);
            livmin[nod]=min(livmin[nod],livmin[gc[nod][i].first]);
            if (livmin[gc[nod][i].first]>=niv[nod]) frd[gc[nod][i].second]=1;
        } else
        if (gc[nod][i].first!=dad[nod]) livmin[nod]=min(livmin[nod],niv[gc[nod][i].first]);

}

int main()
{
    //freopen("1.in","r",stdin);

    scanf("%d %d %d %d",&n,&m,&s,&t);

    for (int i=1;i<=m;i++) {
        scanf("%d %d %d",&x,&y,&z); e[i]={x,y,z};
        g[x].push_back(make_pair(y,z));
        gt[y].push_back(make_pair(x,z));
    }

    for (int i=1;i<=n;i++) {
        d[i]=2e9; heap[i]=i; pos[i]=i;
    }

    d[s]=0; heapup(pos[s]); nr=n;

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)g[x].size();i++)
            if (d[x]+g[x][i].second<d[g[x][i].first]) {
                d[g[x][i].first]=d[x]+g[x][i].second; path[g[x][i].first]=x; heapup(pos[g[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) ds[i]=d[i];

    for (int i=1;i<=n;i++) {
        d[i]=2e9; heap[i]=i; pos[i]=i;
    }

    d[t]=0; heapup(pos[t]); nr=n; mindist=ds[t];

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)gt[x].size();i++)
            if (d[x]+gt[x][i].second<d[gt[x][i].first]) {
                d[gt[x][i].first]=d[x]+gt[x][i].second; heapup(pos[gt[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) dt[i]=d[i];

    for (int i=1;i<=m;i++) {
        int x=e[i].x,y=e[i].y;
        if (ds[x]+e[i].cost+dt[y]==mindist)
            gc[x].push_back(make_pair(y,i)),gc[y].push_back(make_pair(x,i));
    }

    dfs(s);

    for (int i=1;i<=m;i++)
        if (frd[i]==1) puts("YES"); else {
            int x=e[i].x,y=e[i].y,cost=e[i].cost;
            if (mindist-ds[x]-dt[y]-1<=0) puts("NO"); else
                printf("CAN %d\n",cost-(mindist-ds[x]-dt[y]-1));
        }

    return 0;
}


#include <stdio.h>
#include <vector>
#include <algorithm>
#define nmax 100010

using namespace std;

struct edge { int x,y,cost; };

int n,m,s,t,nr,x,y,z,mindist;
int heap[nmax],pos[nmax],d[nmax],path[nmax];
int ds[nmax],dt[nmax],frd[nmax],fr[nmax];
int dad[nmax],niv[nmax],livmin[nmax];
edge e[nmax];
vector < pair <int,int> > g[nmax],gt[nmax],gc[nmax];

void Swap(int &x,int &y)
{
    swap(x,y); swap(pos[x],pos[y]);
}

void heapup(int v)
{
    int k=heap[v];
    while (v>1 && d[heap[v]]<d[heap[v/2]]) {
        Swap(heap[v],heap[v/2]); v=v/2;
    }
    heap[v]=k;
}

void heapdown(int v)
{
    int w=v*2;
    while (w<=nr) {
        if (w+1<=nr && d[heap[w]]>d[heap[w+1]]) w++;
        if (d[heap[v]]>d[heap[w]]) Swap(heap[v],heap[w]); else break;
        v=w; w=w*2;
    }
}

void delete_heap()
{
    Swap(heap[1],heap[nr]); nr--; heapdown(1);
}

void dfs(int nod,int ind)
{
    fr[nod]=1; livmin[nod]=niv[nod];

    for (int i=0;i<(int)gc[nod].size();i++)
        if (fr[gc[nod][i].first]==0) {
            niv[gc[nod][i].first]=niv[nod]+1;
            dad[gc[nod][i].first]=nod;
            dfs(gc[nod][i].first,gc[nod][i].second);
            livmin[nod]=min(livmin[nod],livmin[gc[nod][i].first]);
            if (livmin[gc[nod][i].first]>niv[nod]) frd[gc[nod][i].second]=1;
        } else
        if (gc[nod][i].second!=ind) livmin[nod]=min(livmin[nod],niv[gc[nod][i].first]);

}

int main()
{
    //freopen("1.in","r",stdin);

    scanf("%d %d %d %d",&n,&m,&s,&t);

    for (int i=1;i<=m;i++) {
        scanf("%d %d %d",&x,&y,&z); e[i]={x,y,z};
        g[x].push_back(make_pair(y,z));
        gt[y].push_back(make_pair(x,z));
    }

    for (int i=1;i<=n;i++) {
        d[i]=2e9; heap[i]=i; pos[i]=i;
    }

    d[s]=0; heapup(pos[s]); nr=n;

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)g[x].size();i++)
            if (d[x]+g[x][i].second<d[g[x][i].first]) {
                d[g[x][i].first]=d[x]+g[x][i].second; path[g[x][i].first]=x; heapup(pos[g[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) ds[i]=d[i];

    for (int i=1;i<=n;i++) {
        d[i]=2e9; heap[i]=i; pos[i]=i;
    }

    d[t]=0; heapup(pos[t]); nr=n; mindist=ds[t];

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)gt[x].size();i++)
            if (d[x]+gt[x][i].second<d[gt[x][i].first]) {
                d[gt[x][i].first]=d[x]+gt[x][i].second; heapup(pos[gt[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) dt[i]=d[i];

    for (int i=1;i<=m;i++) {
        int x=e[i].x,y=e[i].y;
        if (ds[x]+e[i].cost+dt[y]==mindist)
            gc[x].push_back(make_pair(y,i)),gc[y].push_back(make_pair(x,i));
    }

    dfs(s,-1);

    for (int i=1;i<=m;i++)
        if (frd[i]==1) puts("YES"); else {
            int x=e[i].x,y=e[i].y,cost=e[i].cost;
            if (mindist-ds[x]-dt[y]-1<=0) puts("NO"); else
                printf("CAN %d\n",cost-(mindist-ds[x]-dt[y]-1));
        }

    return 0;
}


#include <stdio.h>
#include <vector>
#include <algorithm>
#define nmax 100010

using namespace std;

struct edge { int x,y,cost; };

int n,m,s,t,nr,x,y,z,mindist;
int heap[nmax],pos[nmax],d[nmax],path[nmax];
int ds[nmax],dt[nmax],frd[nmax],fr[nmax];
int dad[nmax],niv[nmax],livmin[nmax];
edge e[nmax];
vector < pair <int,int> > g[nmax],gt[nmax],gc[nmax];

void Swap(int &x,int &y)
{
    swap(x,y); swap(pos[x],pos[y]);
}

void heapup(int v)
{
    int k=heap[v];
    while (v>1 && d[heap[v]]<d[heap[v/2]]) {
        Swap(heap[v],heap[v/2]); v=v/2;
    }
    heap[v]=k;
}

void heapdown(int v)
{
    int w=v*2;
    while (w<=nr) {
        if (w+1<=nr && d[heap[w]]>d[heap[w+1]]) w++;
        if (d[heap[v]]>d[heap[w]]) Swap(heap[v],heap[w]); else break;
        v=w; w=w*2;
    }
}

void delete_heap()
{
    Swap(heap[1],heap[nr]); nr--; heapdown(1);
}

void dfs(int nod,int ind)
{
    fr[nod]=1; livmin[nod]=niv[nod];

    for (int i=0;i<(int)gc[nod].size();i++)
        if (fr[gc[nod][i].first]==0) {
            niv[gc[nod][i].first]=niv[nod]+1;
            dad[gc[nod][i].first]=nod;
            dfs(gc[nod][i].first,gc[nod][i].second);
            livmin[nod]=min(livmin[nod],livmin[gc[nod][i].first]);
            if (livmin[gc[nod][i].first]==niv[gc[nod][i].first]) frd[gc[nod][i].second]=1;
        } else
        if (gc[nod][i].second!=ind) livmin[nod]=min(livmin[nod],niv[gc[nod][i].first]);

}

int main()
{
    //freopen("1.in","r",stdin);

    scanf("%d %d %d %d",&n,&m,&s,&t);

    for (int i=1;i<=m;i++) {
        scanf("%d %d %d",&x,&y,&z); e[i]={x,y,z};
        g[x].push_back(make_pair(y,z));
        gt[y].push_back(make_pair(x,z));
    }

    for (int i=1;i<=n;i++) {
        d[i]=2e9; heap[i]=i; pos[i]=i;
    }

    d[s]=0; heapup(pos[s]); nr=n;

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)g[x].size();i++)
            if (d[x]+g[x][i].second<d[g[x][i].first]) {
                d[g[x][i].first]=d[x]+g[x][i].second; path[g[x][i].first]=x; heapup(pos[g[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) ds[i]=d[i];

    for (int i=1;i<=n;i++) {
        d[i]=2e9; heap[i]=i; pos[i]=i;
    }

    d[t]=0; heapup(pos[t]); nr=n; mindist=ds[t];

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)gt[x].size();i++)
            if (d[x]+gt[x][i].second<d[gt[x][i].first]) {
                d[gt[x][i].first]=d[x]+gt[x][i].second; heapup(pos[gt[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) dt[i]=d[i];

    for (int i=1;i<=m;i++) {
        int x=e[i].x,y=e[i].y;
        if (ds[x]+e[i].cost+dt[y]==mindist)
            gc[x].push_back(make_pair(y,i)),gc[y].push_back(make_pair(x,i));
    }

    dfs(s,-1);

    for (int i=1;i<=m;i++)
        if (frd[i]==1) puts("YES"); else {
            int x=e[i].x,y=e[i].y,cost=e[i].cost;
            if (ds[x]==2e9 || dt[y]==2e9 || mindist-ds[x]-dt[y]-1<=0 || cost<=(mindist-ds[x]-dt[y]-1)) puts("NO"); else
                printf("CAN %d\n",cost-(mindist-ds[x]-dt[y]-1));
        }

    return 0;
}


#include <stdio.h>
#include <vector>
#include <algorithm>
#define nmax 100010

using namespace std;
typedef long long int ll;

struct edge { int x,y,cost; };

int n,m,s,t,nr,x,y,z;
int heap[nmax],pos[nmax],frd[nmax],fr[nmax];
int dad[nmax],niv[nmax],livmin[nmax],mindist;
ll ds[nmax],dt[nmax],d[nmax];
edge e[nmax];
vector < pair <int,int> > g[nmax],gt[nmax],gc[nmax];

void Swap(int &x,int &y)
{
    swap(x,y); swap(pos[x],pos[y]);
}

void heapup(int v)
{
    int k=heap[v];
    while (v>1 && d[heap[v]]<d[heap[v/2]]) {
        Swap(heap[v],heap[v/2]); v=v/2;
    }
    heap[v]=k;
}

void heapdown(int v)
{
    int w=v*2;
    while (w<=nr) {
        if (w+1<=nr && d[heap[w]]>d[heap[w+1]]) w++;
        if (d[heap[v]]>d[heap[w]]) Swap(heap[v],heap[w]); else break;
        v=w; w=w*2;
    }
}

void delete_heap()
{
    Swap(heap[1],heap[nr]); nr--; heapdown(1);
}

void dfs(int nod,int ind)
{
    fr[nod]=1; livmin[nod]=niv[nod];

    for (int i=0;i<(int)gc[nod].size();i++)
        if (fr[gc[nod][i].first]==0) {
            niv[gc[nod][i].first]=niv[nod]+1;
            dad[gc[nod][i].first]=nod;
            dfs(gc[nod][i].first,gc[nod][i].second);
            livmin[nod]=min(livmin[nod],livmin[gc[nod][i].first]);
            if (livmin[gc[nod][i].first]>niv[nod]) frd[gc[nod][i].second]=1;
        } else
        if (gc[nod][i].second!=ind) livmin[nod]=min(livmin[nod],niv[gc[nod][i].first]);

}

int main()
{
    //freopen("1.in","r",stdin);

    scanf("%d %d %d %d",&n,&m,&s,&t);

    for (int i=1;i<=m;i++) {
        scanf("%d %d %d",&x,&y,&z); e[i]={x,y,z};
        g[x].push_back(make_pair(y,z));
        gt[y].push_back(make_pair(x,z));
    }

    for (int i=1;i<=n;i++) {
        d[i]=1e18; heap[i]=i; pos[i]=i;
    }

    d[s]=0; heapup(pos[s]); nr=n;

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)g[x].size();i++)
            if (d[x]+g[x][i].second<d[g[x][i].first]) {
                d[g[x][i].first]=d[x]+g[x][i].second; path[g[x][i].first]=x; heapup(pos[g[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) ds[i]=d[i];

    for (int i=1;i<=n;i++) {
        d[i]=1e18; heap[i]=i; pos[i]=i;
    }

    d[t]=0; heapup(pos[t]); nr=n; mindist=ds[t];

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)gt[x].size();i++)
            if (d[x]+gt[x][i].second<d[gt[x][i].first]) {
                d[gt[x][i].first]=d[x]+gt[x][i].second; heapup(pos[gt[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) dt[i]=d[i];

    for (int i=1;i<=m;i++) {
        int x=e[i].x,y=e[i].y;
        if (ds[x]+e[i].cost+dt[y]==mindist)
            gc[x].push_back(make_pair(y,i)),gc[y].push_back(make_pair(x,i));
    }

    dfs(s,-1);

    for (int i=1;i<=m;i++)
        if (frd[i]==1) puts("YES"); else {
            int x=e[i].x,y=e[i].y,cost=e[i].cost;
            if (ds[x]==1e18 || dt[y]==1e18 || mindist-ds[x]-dt[y]-1<=0 || cost<=(mindist-ds[x]-dt[y]-1)) puts("NO"); else
                printf("CAN %d\n",cost-(mindist-ds[x]-dt[y]-1));
        }

    return 0;
}


#include <stdio.h>
#include <vector>
#include <algorithm>
#define nmax 100010

using namespace std;

struct edge { int x,y,cost; };

int n,m,s,t,nr,x,y,z,mindist;
int heap[nmax],pos[nmax],d[nmax],path[nmax];
int ds[nmax],dt[nmax],frd[nmax],fr[nmax];
int dad[nmax],niv[nmax],livmin[nmax];
edge e[nmax];
vector < pair <int,int> > g[nmax],gt[nmax],gc[nmax];

void Swap(int &x,int &y)
{
    swap(x,y); swap(pos[x],pos[y]);
}

void heapup(int v)
{
    int k=heap[v];
    while (v>1 && d[heap[v]]<d[heap[v/2]]) {
        Swap(heap[v],heap[v/2]); v=v/2;
    }
    heap[v]=k;
}

void heapdown(int v)
{
    int w=v*2;
    while (w<=nr) {
        if (w+1<=nr && d[heap[w]]>d[heap[w+1]]) w++;
        if (d[heap[v]]>d[heap[w]]) Swap(heap[v],heap[w]); else break;
        v=w; w=w*2;
    }
}

void delete_heap()
{
    Swap(heap[1],heap[nr]); nr--; heapdown(1);
}

void dfs(int nod,int ind)
{
    fr[nod]=1; livmin[nod]=niv[nod];

    for (int i=0;i<(int)gc[nod].size();i++)
        if (fr[gc[nod][i].first]==0) {
            niv[gc[nod][i].first]=niv[nod]+1;
            dad[gc[nod][i].first]=nod;
            dfs(gc[nod][i].first,gc[nod][i].second);
            livmin[nod]=min(livmin[nod],livmin[gc[nod][i].first]);
            if (livmin[gc[nod][i].first]>niv[nod]) frd[gc[nod][i].second]=1;
        } else
        if (gc[nod][i].second!=ind) livmin[nod]=min(livmin[nod],niv[gc[nod][i].first]);

}

int main()
{
    //freopen("1.in","r",stdin);

    scanf("%d %d %d %d",&n,&m,&s,&t);

    for (int i=1;i<=m;i++) {
        scanf("%d %d %d",&x,&y,&z); e[i]={x,y,z};
        g[x].push_back(make_pair(y,z));
        gt[y].push_back(make_pair(x,z));
    }

    for (int i=1;i<=n;i++) {
        d[i]=2e9; heap[i]=i; pos[i]=i;
    }

    d[s]=0; heapup(pos[s]); nr=n;

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)g[x].size();i++)
            if (d[x]+g[x][i].second<d[g[x][i].first]) {
                d[g[x][i].first]=d[x]+g[x][i].second; path[g[x][i].first]=x; heapup(pos[g[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) ds[i]=d[i];

    for (int i=1;i<=n;i++) {
        d[i]=2e9; heap[i]=i; pos[i]=i;
    }

    d[t]=0; heapup(pos[t]); nr=n; mindist=ds[t];

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)gt[x].size();i++)
            if (d[x]+gt[x][i].second<d[gt[x][i].first]) {
                d[gt[x][i].first]=d[x]+gt[x][i].second; heapup(pos[gt[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) dt[i]=d[i];

    for (int i=1;i<=m;i++) {
        int x=e[i].x,y=e[i].y;
        if (ds[x]+e[i].cost+dt[y]==mindist)
            gc[x].push_back(make_pair(y,i)),gc[y].push_back(make_pair(x,i));
    }

    dfs(s,-1);

    for (int i=1;i<=m;i++)
        if (frd[i]==1) puts("YES"); else {
            int x=e[i].x,y=e[i].y,cost=e[i].cost;
            if (ds[x]==2e9 || dt[y]==2e9 || mindist-ds[x]-dt[y]-1<=0 || cost<=(mindist-ds[x]-dt[y]-1)) puts("NO"); else
                printf("CAN %d\n",cost-(mindist-ds[x]-dt[y]-1));
        }

    return 0;
}


#include <stdio.h>
#include <vector>
#include <algorithm>
#define nmax 100010

using namespace std;
typedef long long int ll;

struct edge { int x,y,cost; };

int n,m,s,t,nr,x,y,z,mindist;
int heap[nmax],pos[nmax],path[nmax];
int frd[nmax],fr[nmax];
int dad[nmax],niv[nmax],livmin[nmax];
ll ds[nmax],dt[nmax],d[nmax];
edge e[nmax];
vector < pair <int,int> > g[nmax],gt[nmax],gc[nmax];

void Swap(int &x,int &y)
{
    swap(x,y); swap(pos[x],pos[y]);
}

void heapup(int v)
{
    int k=heap[v];
    while (v>1 && d[heap[v]]<d[heap[v/2]]) {
        Swap(heap[v],heap[v/2]); v=v/2;
    }
    heap[v]=k;
}

void heapdown(int v)
{
    int w=v*2;
    while (w<=nr) {
        if (w+1<=nr && d[heap[w]]>d[heap[w+1]]) w++;
        if (d[heap[v]]>d[heap[w]]) Swap(heap[v],heap[w]); else break;
        v=w; w=w*2;
    }
}

void delete_heap()
{
    Swap(heap[1],heap[nr]); nr--; heapdown(1);
}

void dfs(int nod,int ind)
{
    fr[nod]=1; livmin[nod]=niv[nod];

    for (int i=0;i<(int)gc[nod].size();i++)
        if (fr[gc[nod][i].first]==0) {
            niv[gc[nod][i].first]=niv[nod]+1;
            dad[gc[nod][i].first]=nod;
            dfs(gc[nod][i].first,gc[nod][i].second);
            livmin[nod]=min(livmin[nod],livmin[gc[nod][i].first]);
            if (livmin[gc[nod][i].first]>niv[nod]) frd[gc[nod][i].second]=1;
        } else
        if (gc[nod][i].second!=ind) livmin[nod]=min(livmin[nod],niv[gc[nod][i].first]);

}

int main()
{
    //freopen("1.in","r",stdin);

    scanf("%d %d %d %d",&n,&m,&s,&t);

    for (int i=1;i<=m;i++) {
        scanf("%d %d %d",&x,&y,&z); e[i]={x,y,z};
        g[x].push_back(make_pair(y,z));
        gt[y].push_back(make_pair(x,z));
    }

    for (int i=1;i<=n;i++) {
        d[i]=1e18; heap[i]=i; pos[i]=i;
    }

    d[s]=0; heapup(pos[s]); nr=n;

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)g[x].size();i++)
            if (d[x]+g[x][i].second<d[g[x][i].first]) {
                d[g[x][i].first]=d[x]+g[x][i].second; path[g[x][i].first]=x; heapup(pos[g[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) ds[i]=d[i];

    for (int i=1;i<=n;i++) {
        d[i]=1e18; heap[i]=i; pos[i]=i;
    }

    d[t]=0; heapup(pos[t]); nr=n; mindist=ds[t];

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)gt[x].size();i++)
            if (d[x]+gt[x][i].second<d[gt[x][i].first]) {
                d[gt[x][i].first]=d[x]+gt[x][i].second; heapup(pos[gt[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) dt[i]=d[i];

    for (int i=1;i<=m;i++) {
        int x=e[i].x,y=e[i].y;
        if (ds[x]+e[i].cost+dt[y]==mindist)
            gc[x].push_back(make_pair(y,i)),gc[y].push_back(make_pair(x,i));
    }

    dfs(s,-1);

    for (int i=1;i<=m;i++)
        if (frd[i]==1) puts("YES"); else {
            int x=e[i].x,y=e[i].y,cost=e[i].cost;
            if (ds[x]==1e18 || dt[y]==1e18 || mindist-ds[x]-dt[y]-1<=0 || cost<=(mindist-ds[x]-dt[y]-1)) puts("NO"); else
                printf("CAN %d\n",cost-(mindist-ds[x]-dt[y]-1));
        }

    return 0;
}


#include <stdio.h>
#include <vector>
#include <algorithm>
#define nmax 100010

using namespace std;

struct edge { int x,y,cost; };

int n,m,s,t,nr,x,y,z,mindist;
int heap[nmax],pos[nmax],d[nmax],path[nmax];
int ds[nmax],dt[nmax],frd[nmax],fr[nmax];
int dad[nmax],niv[nmax],livmin[nmax];
edge e[nmax];
vector < pair <int,int> > g[nmax],gt[nmax],gc[nmax];

void Swap(int &x,int &y)
{
    swap(x,y); swap(pos[x],pos[y]);
}

void heapup(int v)
{
    int k=heap[v];
    while (v>1 && d[heap[v]]<d[heap[v/2]]) {
        Swap(heap[v],heap[v/2]); v=v/2;
    }
    heap[v]=k;
}

void heapdown(int v)
{
    int w=v*2;
    while (w<=nr) {
        if (w+1<=nr && d[heap[w]]>d[heap[w+1]]) w++;
        if (d[heap[v]]>d[heap[w]]) Swap(heap[v],heap[w]); else break;
        v=w; w=w*2;
    }
}

void delete_heap()
{
    Swap(heap[1],heap[nr]); nr--; heapdown(1);
}

void dfs(int nod)
{
    fr[nod]=1; livmin[nod]=niv[nod];

    for (int i=0;i<(int)gc[nod].size();i++)
        if (fr[gc[nod][i].first]==0) {
            niv[gc[nod][i].first]=niv[nod]+1;
            dad[gc[nod][i].first]=nod;
            dfs(gc[nod][i].first);
            livmin[nod]=min(livmin[nod],livmin[gc[nod][i].first]);
            if (livmin[gc[nod][i].first]>niv[nod]) frd[gc[nod][i].second]=1;
        } else
        if (gc[nod][i].first!=dad[nod]) livmin[nod]=min(livmin[nod],niv[gc[nod][i].first]);

}

int main()
{
    //freopen("1.in","r",stdin);

    scanf("%d %d %d %d",&n,&m,&s,&t);

    for (int i=1;i<=m;i++) {
        scanf("%d %d %d",&x,&y,&z); e[i]={x,y,z};
        g[x].push_back(make_pair(y,z));
        gt[y].push_back(make_pair(x,z));
    }

    for (int i=1;i<=n;i++) {
        d[i]=2e9; heap[i]=i; pos[i]=i;
    }

    d[s]=0; heapup(pos[s]); nr=n;

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)g[x].size();i++)
            if (d[x]+g[x][i].second<d[g[x][i].first]) {
                d[g[x][i].first]=d[x]+g[x][i].second; path[g[x][i].first]=x; heapup(pos[g[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) ds[i]=d[i];

    for (int i=1;i<=n;i++) {
        d[i]=2e9; heap[i]=i; pos[i]=i;
    }

    d[t]=0; heapup(pos[t]); nr=n; mindist=ds[t];

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)gt[x].size();i++)
            if (d[x]+gt[x][i].second<d[gt[x][i].first]) {
                d[gt[x][i].first]=d[x]+gt[x][i].second; heapup(pos[gt[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) dt[i]=d[i];

    for (int i=1;i<=m;i++) {
        int x=e[i].x,y=e[i].y;
        if (ds[x]+e[i].cost+dt[y]==mindist)
            gc[x].push_back(make_pair(y,i)),gc[y].push_back(make_pair(x,i));
    }

    dfs(s);

    for (int i=1;i<=m;i++)
        if (frd[i]==1) puts("YES"); else {
            int x=e[i].x,y=e[i].y,cost=e[i].cost;
            if (mindist-ds[x]-dt[y]-1<=0) puts("NO"); else
                printf("CAN %d\n",cost-(mindist-ds[x]-dt[y]-1));
        }

    return 0;
}


#include <stdio.h>
#include <vector>
#include <algorithm>
#define nmax 100010

using namespace std;
typedef long long int ll;

struct edge { int x,y,cost; };

int n,m,s,t,nr,x,y,z;
int heap[nmax],pos[nmax],frd[nmax],fr[nmax];
int dad[nmax],niv[nmax],livmin[nmax];
ll ds[nmax],dt[nmax],d[nmax],mindist;
edge e[nmax];
vector < pair <int,int> > g[nmax],gt[nmax],gc[nmax];

void Swap(int &x,int &y)
{
    swap(x,y); swap(pos[x],pos[y]);
}

void heapup(int v)
{
    int k=heap[v];
    while (v>1 && d[heap[v]]<d[heap[v/2]]) {
        Swap(heap[v],heap[v/2]); v=v/2;
    }
    heap[v]=k;
}

void heapdown(int v)
{
    int w=v*2;
    while (w<=nr) {
        if (w+1<=nr && d[heap[w]]>d[heap[w+1]]) w++;
        if (d[heap[v]]>d[heap[w]]) Swap(heap[v],heap[w]); else break;
        v=w; w=w*2;
    }
}

void delete_heap()
{
    Swap(heap[1],heap[nr]); nr--; heapdown(1);
}

void dfs(int nod,int ind)
{
    fr[nod]=1; livmin[nod]=niv[nod];

    for (int i=0;i<(int)gc[nod].size();i++)
        if (fr[gc[nod][i].first]==0) {
            niv[gc[nod][i].first]=niv[nod]+1;
            dad[gc[nod][i].first]=nod;
            dfs(gc[nod][i].first,gc[nod][i].second);
            livmin[nod]=min(livmin[nod],livmin[gc[nod][i].first]);
            if (livmin[gc[nod][i].first]>niv[nod]) frd[gc[nod][i].second]=1;
        } else
        if (gc[nod][i].second!=ind) livmin[nod]=min(livmin[nod],niv[gc[nod][i].first]);

}

int main()
{
    //freopen("1.in","r",stdin);

    scanf("%d %d %d %d",&n,&m,&s,&t);

    for (int i=1;i<=m;i++) {
        scanf("%d %d %d",&x,&y,&z); e[i]={x,y,z};
        g[x].push_back(make_pair(y,z));
        gt[y].push_back(make_pair(x,z));
    }

    for (int i=1;i<=n;i++) {
        d[i]=1e18; heap[i]=i; pos[i]=i;
    }

    d[s]=0; heapup(pos[s]); nr=n;

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)g[x].size();i++)
            if (d[x]+g[x][i].second<d[g[x][i].first]) {
                d[g[x][i].first]=d[x]+g[x][i].second; heapup(pos[g[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) ds[i]=d[i];

    for (int i=1;i<=n;i++) {
        d[i]=1e18; heap[i]=i; pos[i]=i;
    }

    d[t]=0; heapup(pos[t]); nr=n; mindist=ds[t];

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)gt[x].size();i++)
            if (d[x]+gt[x][i].second<d[gt[x][i].first]) {
                d[gt[x][i].first]=d[x]+gt[x][i].second; heapup(pos[gt[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) dt[i]=d[i];

    for (int i=1;i<=m;i++) {
        int x=e[i].x,y=e[i].y;
        if (ds[x]+e[i].cost+dt[y]==mindist)
            gc[x].push_back(make_pair(y,i)),gc[y].push_back(make_pair(x,i));
    }

    dfs(s,-1);

    for (int i=1;i<=m;i++)
        if (frd[i]==1) puts("YES"); else {
            int x=e[i].x,y=e[i].y,cost=e[i].cost;
            if (ds[x]==1e18 || dt[y]==1e18 || mindist-ds[x]-dt[y]-1<=0 || cost<=(mindist-ds[x]-dt[y]-1)) puts("NO"); else
                printf("CAN %d\n",cost-(mindist-ds[x]-dt[y]-1));
        }

    return 0;
}


#include <stdio.h>
#include <vector>
#include <algorithm>
#define nmax 100010

using namespace std;

struct edge { int x,y,cost; };

int n,m,s,t,nr,x,y,z,mindist;
int heap[nmax],pos[nmax],d[nmax],path[nmax];
int ds[nmax],dt[nmax],frd[nmax],fr[nmax];
int dad[nmax],niv[nmax],livmin[nmax];
edge e[nmax];
vector < pair <int,int> > g[nmax],gt[nmax],gc[nmax];

void Swap(int &x,int &y)
{
    swap(x,y); swap(pos[x],pos[y]);
}

void heapup(int v)
{
    int k=heap[v];
    while (v>1 && d[heap[v]]<d[heap[v/2]]) {
        Swap(heap[v],heap[v/2]); v=v/2;
    }
    heap[v]=k;
}

void heapdown(int v)
{
    int w=v*2;
    while (w<=nr) {
        if (w+1<=nr && d[heap[w]]>d[heap[w+1]]) w++;
        if (d[heap[v]]>d[heap[w]]) Swap(heap[v],heap[w]); else break;
        v=w; w=w*2;
    }
}

void delete_heap()
{
    Swap(heap[1],heap[nr]); nr--; heapdown(1);
}

void dfs(int nod,int ind)
{
    fr[nod]=1; livmin[nod]=niv[nod];

    for (int i=0;i<(int)gc[nod].size();i++)
        if (fr[gc[nod][i].first]==0) {
            niv[gc[nod][i].first]=niv[nod]+1;
            dad[gc[nod][i].first]=nod;
            dfs(gc[nod][i].first,gc[nod][i].second);
            livmin[nod]=min(livmin[nod],livmin[gc[nod][i].first]);
            if (livmin[gc[nod][i].first]>niv[nod]) frd[gc[nod][i].second]=1;
        } else
        if (gc[nod][i].second!=ind) livmin[nod]=min(livmin[nod],niv[gc[nod][i].first]);

}

int main()
{
    //freopen("1.in","r",stdin);

    scanf("%d %d %d %d",&n,&m,&s,&t);

    for (int i=1;i<=m;i++) {
        scanf("%d %d %d",&x,&y,&z); e[i]={x,y,z};
        g[x].push_back(make_pair(y,z));
        gt[y].push_back(make_pair(x,z));
    }

    for (int i=1;i<=n;i++) {
        d[i]=2e9; heap[i]=i; pos[i]=i;
    }

    d[s]=0; heapup(pos[s]); nr=n;

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)g[x].size();i++)
            if (d[x]+g[x][i].second<d[g[x][i].first]) {
                d[g[x][i].first]=d[x]+g[x][i].second; path[g[x][i].first]=x; heapup(pos[g[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) ds[i]=d[i];

    for (int i=1;i<=n;i++) {
        d[i]=2e9; heap[i]=i; pos[i]=i;
    }

    d[t]=0; heapup(pos[t]); nr=n; mindist=ds[t];

    while (nr>0) {
        int x=heap[1]; delete_heap();
        for (int i=0;i<(int)gt[x].size();i++)
            if (d[x]+gt[x][i].second<d[gt[x][i].first]) {
                d[gt[x][i].first]=d[x]+gt[x][i].second; heapup(pos[gt[x][i].first]);
        }
    }

    for (int i=1;i<=n;i++) dt[i]=d[i];

    for (int i=1;i<=m;i++) {
        int x=e[i].x,y=e[i].y;
        if (ds[x]+e[i].cost+dt[y]==mindist)
            gc[x].push_back(make_pair(y,i)),gc[y].push_back(make_pair(x,i));
    }

    dfs(s,-1);

    for (int i=1;i<=m;i++)
        if (frd[i]==1) puts("YES"); else {
            int x=e[i].x,y=e[i].y,cost=e[i].cost;
            if (mindist-ds[x]-dt[y]-1<=0 || cost<=(mindist-ds[x]-dt[y]-1)) puts("NO"); else
                printf("CAN %d\n",cost-(mindist-ds[x]-dt[y]-1));
        }

    return 0;
}


#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#define INF 0xffffffff

using namespace std;
const long long maxn = 1e5+10;
const long long mod = 1e9+13;

struct edge{
    long long v,to,cost;
    edge(long long t,long long c):to(t),cost(c){};
    edge(long long v, long long t,long long c):v(v),to(t),cost(c){};
    bool operator < (const edge & a) const{
        return cost > a.cost;
    }
};

vector <edge> G_a[maxn];
vector <edge> G_b[maxn];
vector <edge> e;

void addedge(long long from, long long to, long long cost){
    G_a[from].push_back(edge(to, cost));
    G_b[to].push_back(edge(from, cost));
}
long long dis_a[maxn];
long long dis_b[maxn];
long long cnt_a[maxn];
long long cnt_b[maxn];
long long n;

void Dijkstra(long long s,long long cnt[], long long dis[],bool flag){
    for (long long i = 0 ; i <= n ; i ++){
        dis[i] = INF;cnt[i] = 0;
    }
    dis[s] = 0;cnt[s] = 1;
    priority_queue<edge> Q;
    Q.push(edge(s,dis[s]));
    while(!Q.empty()){
        edge tmp = Q.top();Q.pop();
        long long limt = flag?G_a[tmp.to].size():G_b[tmp.to].size();
        for(long long i = 0 ; i < limt; i ++){
            edge& next = flag ? G_a[tmp.to][i]:G_b[tmp.to][i];
            if(dis[next.to] == tmp.cost+next.cost)
                cnt[next.to] = (cnt[tmp.to]+cnt[next.to])%mod;
            if(dis[next.to] > tmp.cost + next.cost){
                cnt[next.to] = cnt[tmp.to];
                dis[next.to] = tmp.cost + next.cost;
                Q.push(edge(next.to,dis[next.to]));
            }
        }
    }
}

int main(){
    long long m,s,t;
    cin >>n>>m>>s>>t;
    long long from, to, cos;
    for (long long i = 0 ; i < m ; i ++){
        scanf("%I64d %I64d %I64d",&from,&to,&cos);
        addedge(from,to,cos);
        e.push_back(edge(from,to,cos));
    }
    Dijkstra(s,cnt_a,dis_a,true);
    Dijkstra(t,cnt_b,dis_b,false);
    for(long long i = 0 ; i < m ; i ++){

        if(dis_a[e[i].v]+e[i].cost+dis_b[e[i].to] == dis_a[t] && (cnt_a[e[i].v]*cnt_b[e[i].to])%mod == cnt_a[t])
            puts("YES");
        else{
            long long ect = dis_a[t]-dis_a[e[i].v]-dis_b[e[i].to]-1;
            if(ect < 1 || e[i].cost == 1)
                puts("NO");
            else printf ("CAN %I64d\n",e[i].cost-ect);
        }
    }
}


#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#define INF __INT64_MAX__

using namespace std;
const long long maxn = 1e5+10;
const long long mod = 1e9+13;

struct edge{
    long long v,to,cost;
    edge(long long t,long long c):to(t),cost(c){};
    edge(long long v, long long t,long long c):v(v),to(t),cost(c){};
    bool operator < (const edge & a) const{
        return cost > a.cost;
    }
};

vector <edge> G_a[maxn];
vector <edge> G_b[maxn];
vector <edge> e;

void addedge(long long from, long long to, long long cost){
    G_a[from].push_back(edge(to, cost));
    G_b[to].push_back(edge(from, cost));
}
long long dis_a[maxn];
long long dis_b[maxn];
long long cnt_a[maxn];
long long cnt_b[maxn];
long long n;

void Dijkstra(long long s,long long cnt[], long long dis[],bool flag){
    for (long long i = 0 ; i <= n ; i ++){
        dis[i] = INF;cnt[i] = 0;
    }
    dis[s] = 0;cnt[s] = 1;
    priority_queue<edge> Q;
    Q.push(edge(s,dis[s]));
    while(!Q.empty()){
        edge tmp = Q.top();Q.pop();
        int limt = flag?G_a[tmp.to].size():G_b[tmp.to].size();
        for(long long i = 0 ; i < limt; i ++){
            edge& next = flag ? G_a[tmp.to][i]:G_b[tmp.to][i];
            if(dis[next.to] == tmp.cost+next.cost)
                cnt[next.to] = (cnt[tmp.to]+cnt[next.to])%mod;
            if(dis[next.to] > tmp.cost + next.cost){
                cnt[next.to] = cnt[tmp.to];
                dis[next.to] = tmp.cost + next.cost;
                Q.push(edge(next.to,dis[next.to]));
            }
        }
    }
}

int main(){
    long long m,s,t;
    cin >>n>>m>>s>>t;
    long long from, to, cos;
    for (long long i = 0 ; i < m ; i ++){
        scanf("%I64d %I64d %I64d",&from,&to,&cos);
        addedge(from,to,cos);
        e.push_back(edge(from,to,cos));
    }
    Dijkstra(s,cnt_a,dis_a,true);
    Dijkstra(t,cnt_b,dis_b,false);
    for(long long i = 0 ; i < m ; i ++){

        if(dis_a[e[i].v]+e[i].cost+dis_b[e[i].to] == dis_a[t] && (cnt_a[e[i].v]*cnt_b[e[i].to])%mod == cnt_a[t])
            puts("YES");
        else{
            long long ect = dis_a[t]-dis_a[e[i].v]-dis_b[e[i].to]-1;
            if(ect < 1 || e[i].cost == 1)
                puts("NO");
            else printf ("CAN %I64d\n",e[i].cost-ect);
        }
    }
}


#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#define INF 0xffffffff

using namespace std;
const long long maxn = 1e5+10;
const long long mod = 1e9+13;

struct edge{
    long long v,to,cost;
    edge(long long t,long long c):to(t),cost(c){};
    edge(long long v, long long t,long long c):v(v),to(t),cost(c){};
    bool operator < (const edge & a) const{
        return cost > a.cost;
    }
};

vector <edge> G_a[maxn];
vector <edge> G_b[maxn];
vector <edge> e;

void addedge(long long from, long long to, long long cost){
    G_a[from].push_back(edge(to, cost));
    G_b[to].push_back(edge(from, cost));
}
long long dis_a[maxn];
long long dis_b[maxn];
long long cnt_a[maxn];
long long cnt_b[maxn];
long long n;

void Dijkstra(long long s,long long cnt[], long long dis[],bool flag){
    for (long long i = 0 ; i <= n ; i ++){
        dis[i] = INF;cnt[i] = 0;
    }
    dis[s] = 0;cnt[s] = 1;
    priority_queue<edge> Q;
    Q.push(edge(s,dis[s]));
    while(!Q.empty()){
        edge tmp = Q.top();Q.pop();
        int limt = flag?G_a[tmp.to].size():G_b[tmp.to].size();
        for(long long i = 0 ; i < limt; i ++){
            edge& next = flag ? G_a[tmp.to][i]:G_b[tmp.to][i];
            if(dis[next.to] == tmp.cost+next.cost)
                cnt[next.to] = (cnt[tmp.to]+cnt[next.to])%mod;
            if(dis[next.to] > tmp.cost + next.cost){
                cnt[next.to] = cnt[tmp.to];
                dis[next.to] = tmp.cost + next.cost;
                Q.push(edge(next.to,dis[next.to]));
            }
        }
    }
}

int main(){
    long long m,s,t;
    cin >>n>>m>>s>>t;
    long long from, to, cos;
    for (long long i = 0 ; i < m ; i ++){
        scanf("%I64d %I64d %I64d",&from,&to,&cos);
        addedge(from,to,cos);
        e.push_back(edge(from,to,cos));
    }
    Dijkstra(s,cnt_a,dis_a,true);
    Dijkstra(t,cnt_b,dis_b,false);
    for(long long i = 0 ; i < m ; i ++){

        if(dis_a[e[i].v]+e[i].cost+dis_b[e[i].to] == dis_a[t] && (cnt_a[e[i].v]*cnt_b[e[i].to])%mod == cnt_a[t])
            puts("YES");
        else{
            long long ect = dis_a[t]-dis_a[e[i].v]-dis_b[e[i].to]-1;
            if(ect < 1 || e[i].cost == 1)
                puts("NO");
            else printf ("CAN %I64d\n",e[i].cost-ect);
        }
    }
}


#include <map>
#include <set>
#include <queue>
#include <stack>
#include <bitset>
#include <time.h>
#include <string>
#include <vector>
#include <math.h>
#include <cstdio>
#include <cassert>
#include <iostream>
#include <algorithm>

using namespace std;

#define ft first
#define sc second
#define mp make_pair
#define all(a) a.begin(), a.end()
#define forn(i, n) for (int i = 0; i < int(n); i++)

typedef long long li;
typedef long double ld;
typedef pair <li, li> pli;
typedef pair <int, int> pii;

const int N = 200000;
const li INF = li(1e18);

int n;

bool ok[N];

struct edge
{
    int v, to, w, idx;
    edge () { }
    edge(int v, int to, int w, int idx) : v(v), to(to), w(w), idx(idx) { }
};

vector <li> d1, d2;

vector <edge> e, g[N], tg[N];

void sssp(int v, vector <li> & d, bool f)
{
    d.assign(n, INF);
    d[v] = 0;
    set < pair <li, int> > s;
    s.insert(mp(d[v], v));

    while(!s.empty())
    {
        v = s.begin()->sc;
        li dv = s.begin()->ft;
        s.erase(s.begin());

        forn(i, f ? tg[v].size() : g[v].size())
        {
            int to = f ? tg[v][i].to : g[v][i].to;
            int w = f ? tg[v][i].w : g[v][i].w;

            if(d[to] > dv + w)
            {
                d[to] = dv + w;
                s.insert(mp(d[to], to));
            }
        }
    }
}

bool cmp(pair <pli, int> a, pair <pli, int> b)
{
    return a.ft.sc > b.ft.sc;
}

int main()
{

    int m, s, t;
    scanf("%d %d %d %d", &n, &m, &s, &t);
    s--; t--;

    forn(i, m)
    {
        int a, to, w;
        scanf("%d %d %d", &a, &to, &w);
        a--; to--;
        g[a].push_back(edge(-1, to, w, i));
        tg[to].push_back(edge(-1, a, w, i));
        e.push_back(edge(a, to, w, i));
    }

    sssp(s, d1, false);
    sssp(t, d2, true);

    vector <pair <pli, int> > ds;

    forn(i, m)
    {
        int v = e[i].v, w = e[i].w, to = e[i].to;
        if(d1[v] + w + d2[to] == d1[t])
            ds.push_back(mp(mp(d1[v], d1[to]), e[i].idx));

    }

    sort(all(ds), cmp);

    set <pli> st;
    set <pli> changed;

    forn(i, ds.size())
    {
        li l = ds[i].ft.ft, r = ds[i].ft.sc;
        auto it = st.lower_bound(mp(l, -1));

        if(it == st.end() || it->sc >= r)
            st.insert(mp(r, l));
        else
        {
            li lf = it->sc, rt = it->ft;
            changed.insert(*it);
            st.erase(it);
            st.insert(mp(rt,min(lf, l)));
            changed.insert(mp(rt,min(lf, l)));
        }
    }

    vector <int> res;

    forn(i, ds.size())
    {
        li l = ds[i].ft.ft, r = ds[i].ft.sc;
        auto it = st.find(mp(r, l));
        auto it2 = changed.find(mp(r, l));
        if(it != st.end() && it2 == changed.end())
            ok[ds[i].sc] = true;
    }

    forn(i, m)
    {
        int v = e[i].v, to = e[i].to, w = e[i].w;

        if(ok[e[i].idx])
            puts("YES");
        else if(d1[t] - d1[v] - d2[to] - 1 > 0)
            printf("CAN %d\n", w - (d1[t] - d1[v] - d2[to] - 1));
        else
            puts("NO");
    }

    return 0;
}


#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#define INF 0x3f3f3f3f3f3f3f3f

using namespace std;
const long long maxn = 1e5+10;
const long long mod = 1e9+13;

struct edge{
    long long v,to,cost;
    edge(long long t,long long c):to(t),cost(c){};
    edge(long long v, long long t,long long c):v(v),to(t),cost(c){};
    bool operator < (const edge & a) const{
        return cost > a.cost;
    }
};

vector <edge> G_a[maxn];
vector <edge> G_b[maxn];
vector <edge> e;

void addedge(long long from, long long to, long long cost){
    G_a[from].push_back(edge(to, cost));
    G_b[to].push_back(edge(from, cost));
}
long long dis_a[maxn];
long long dis_b[maxn];
long long cnt_a[maxn];
long long cnt_b[maxn];
long long n;

void Dijkstra(long long s,long long cnt[], long long dis[],bool flag){
    for (long long i = 0 ; i <= n ; i ++){
        dis[i] = INF;cnt[i] = 0;
    }
    dis[s] = 0;cnt[s] = 1;
    priority_queue<edge> Q;
    Q.push(edge(s,dis[s]));
    while(!Q.empty()){
        edge tmp = Q.top();Q.pop();
        long long limt = flag?G_a[tmp.to].size():G_b[tmp.to].size();
        for(long long i = 0 ; i < limt; i ++){
            edge& next = flag ? G_a[tmp.to][i]:G_b[tmp.to][i];
            if(dis[next.to] == tmp.cost+next.cost)
                cnt[next.to] = (cnt[tmp.to]+cnt[next.to])%mod;
            if(dis[next.to] > tmp.cost + next.cost){
                cnt[next.to] = cnt[tmp.to];
                dis[next.to] = tmp.cost + next.cost;
                Q.push(edge(next.to,dis[next.to]));
            }
        }
    }
}

int main(){
    long long m,s,t;
    cin >>n>>m>>s>>t;
    long long from, to, cos;
    for (long long i = 0 ; i < m ; i ++){
        scanf("%I64d %I64d %I64d",&from,&to,&cos);
        addedge(from,to,cos);
        e.push_back(edge(from,to,cos));
    }
    Dijkstra(s,cnt_a,dis_a,true);
    Dijkstra(t,cnt_b,dis_b,false);
    for(long long i = 0 ; i < m ; i ++){

        if(dis_a[e[i].v]+e[i].cost+dis_b[e[i].to] == dis_a[t] && (cnt_a[e[i].v]*cnt_b[e[i].to])%mod == cnt_a[t])
            puts("YES");
        else{
            long long ect = dis_a[t]-dis_a[e[i].v]-dis_b[e[i].to]-1;
            if(ect < 1 || e[i].cost == 1)
                puts("NO");
            else printf ("CAN %I64d\n",e[i].cost-ect);
        }
    }
}


#include <bits/stdc++.h>

#define INF 0x3f3f3f3f3f3f3f3f
typedef long long ll;

using namespace std;
const ll maxn = 1e5+10;
const ll mod = 1e9+13;

struct edge{
    ll v,to,cost;
    edge(ll t,ll c):to(t),cost(c){};
    edge(ll v, ll t,ll c):v(v),to(t),cost(c){};
    bool operator < (const edge & a) const{
        return cost > a.cost;
    }
};

vector <edge> G_a[maxn];
vector <edge> G_b[maxn];
vector <edge> e;

void addedge(ll from, ll to, ll cost){
    G_a[from].push_back(edge(to, cost));
    G_b[to].push_back(edge(from, cost));
}
ll dis_a[maxn];
ll dis_b[maxn];
ll cnt_a[maxn];
ll cnt_b[maxn];
ll n;

void Dijkstra(ll s,ll cnt[], ll dis[],bool flag){
    for (ll i = 0 ; i <= n ; i ++){
        dis[i] = INF;cnt[i] = 0;
    }
    dis[s] = 0;cnt[s] = 1;
    priority_queue<edge> Q;
    Q.push(edge(s,dis[s]));
    while(!Q.empty()){
        edge tmp = Q.top();Q.pop();
        ll limt = flag?G_a[tmp.to].size():G_b[tmp.to].size();
        for(ll i = 0 ; i < limt; i ++){
            edge& next = flag ? G_a[tmp.to][i]:G_b[tmp.to][i];
            if(dis[next.to] == tmp.cost+next.cost)
                cnt[next.to] = (cnt[tmp.to]+cnt[next.to])%mod;
            if(dis[next.to] > tmp.cost + next.cost){
                cnt[next.to] = cnt[tmp.to];
                dis[next.to] = tmp.cost + next.cost;
                Q.push(edge(next.to,dis[next.to]));
            }
        }
    }
}

int main(){
    ll m,s,t;
    cin >>n>>m>>s>>t;
    ll from, to, cos;
    for (ll i = 0 ; i < m ; i ++){
        scanf("%I64d %I64d %I64d",&from,&to,&cos);
        addedge(from,to,cos);
        e.push_back(edge(from,to,cos));
    }
    Dijkstra(s,cnt_a,dis_a,true);
    Dijkstra(t,cnt_b,dis_b,false);
    for(ll i = 0 ; i < m ; i ++){

        if(dis_a[e[i].v]+e[i].cost+dis_b[e[i].to] == dis_a[t] && (cnt_a[e[i].v]*cnt_b[e[i].to])%mod == cnt_a[t])
            puts("YES");
        else{
            ll ect = dis_a[t]-dis_a[e[i].v]-dis_b[e[i].to]-1;
            if(ect < 1 || e[i].cost == 1)
                puts("NO");
            else printf ("CAN %I64d\n",e[i].cost-ect);
        }
    }
}


#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#define INF 0xffffffff

using namespace std;
const long long maxn = 1e5+10;
const long long mod = 1000776999;

struct edge{
    long long v,to,cost;
    edge(long long t,long long c):to(t),cost(c){};
    edge(long long v, long long t,long long c):v(v),to(t),cost(c){};
    bool operator < (const edge & a) const{
        return cost > a.cost;
    }
};

vector <edge> G_a[maxn];
vector <edge> G_b[maxn];
vector <edge> e;

void addedge(long long from, long long to, long long cost){
    G_a[from].push_back(edge(to, cost));
    G_b[to].push_back(edge(from, cost));
}
long long dis_a[maxn];
long long dis_b[maxn];
long long cnt_a[maxn];
long long cnt_b[maxn];
long long n;

void Dijkstra(long long s,long long cnt[], long long dis[],bool flag){
    for (long long i = 0 ; i <= n ; i ++){
        dis[i] = INF;cnt[i] = 0;
    }
    dis[s] = 0;cnt[s] = 1;
    priority_queue<edge> Q;
    Q.push(edge(s,dis[s]));
    while(!Q.empty()){
        edge tmp = Q.top();Q.pop();
        int limt = flag?G_a[tmp.to].size():G_b[tmp.to].size();
        for(long long i = 0 ; i < limt; i ++){
            edge& next = flag ? G_a[tmp.to][i]:G_b[tmp.to][i];
            if(dis[next.to] == tmp.cost+next.cost)
                cnt[next.to] = (cnt[tmp.to]+cnt[next.to])%mod;
            if(dis[next.to] > tmp.cost + next.cost){
                cnt[next.to] = cnt[tmp.to];
                dis[next.to] = tmp.cost + next.cost;
                Q.push(edge(next.to,dis[next.to]));
            }
        }
    }
}

int main(){
    long long m,s,t;
    cin >>n>>m>>s>>t;
    long long from, to, cos;
    for (long long i = 0 ; i < m ; i ++){
        scanf("%I64d %I64d %I64d",&from,&to,&cos);
        addedge(from,to,cos);
        e.push_back(edge(from,to,cos));
    }
    Dijkstra(s,cnt_a,dis_a,true);
    Dijkstra(t,cnt_b,dis_b,false);
    for(long long i = 0 ; i < m ; i ++){

        if(dis_a[e[i].v]+e[i].cost+dis_b[e[i].to] == dis_a[t] && (cnt_a[e[i].v]*cnt_b[e[i].to])%mod == cnt_a[t])
            puts("YES");
        else{
            long long ect = dis_a[t]-dis_a[e[i].v]-dis_b[e[i].to]-1;
            if(ect < 1 || e[i].cost == 1)
                puts("NO");
            else printf ("CAN %I64d\n",e[i].cost-ect);
        }
    }
}