/*
 * =====================================================================================
 *
 *       Filename:  314_div2_E_president_and_roads.cpp
 *
 *    Description:  http://codeforces.com/contest/567/problem/E
 *
 *        Version:  1.0
 *        Created:  09/03/2015 05:53:58 PM
 *       Revision:  none
 *       Compiler:  gcc/g++
 *
 *         Author:  Marius-Constantin Melemciuc
 *          email:
 *   Organization:
 *
 * =====================================================================================
 */

#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
#include <stack>
#include <queue>
#include <utility>
#include <limits>

using namespace std;

vector<vector<pair<int, int> > > graph;
vector<bool> visited;

vector<vector<pair<int, int> > > graph_inversed;

vector<vector<pair<int, int> > > prevs;
vector<pair<pair<int, int>, int> > edges;

vector<vector<int> > graph_i;
vector<vector<int> >::iterator it2;

class Cmp {
public:
    bool operator()(const pair<int, int>& a, const pair<int, int>& b) {
        return (a.second > b.second)? true: false; // decreasing order
    }
};

vector<long long int> dijkstra(int n, int source) {
    vector<bool> visited_vertices(n, false);
    vector<long long int> distance(n, numeric_limits<int>::max());
    priority_queue<pair<long long int, long long int>,
                   vector<pair<long long int, long long int> >,
                   Cmp> pq;

    distance[source] = 0;
    pq.push(make_pair(source, distance[source]));

    while (!pq.empty()) {
        int x = pq.top().first;

        pq.pop();

        if (visited_vertices[x]) {
            continue;
        }
        visited_vertices[x] = true;

        for (auto it = graph[x].begin(); it != graph[x].end(); it++) {
            int y    = it->first;
            int cost = it->second;

            if (distance[y] > distance[x] + cost) {

                distance[y] = distance[x] + cost;
                pq.push(make_pair(y, distance[y]));
            }
        }
    }

    return distance;
}

vector<long long int> dijkstraOnInversedGraph(int n, int source) {
    vector<bool> visited_vertices(n, false);
    vector<long long int> distance(n, numeric_limits<int>::max());
    priority_queue<pair<long long int, long long int>,
                   vector<pair<long long int, long long int> >,
                   Cmp> pq;

    distance[source] = 0;
    pq.push(make_pair(source, distance[source]));

    while (!pq.empty()) {
        int x = pq.top().first;

        pq.pop();

        if (visited_vertices[x]) {
            continue;
        }
        visited_vertices[x] = true;

        for (auto it = graph_inversed[x].begin(); it != graph_inversed[x].end(); it++) {
            int y    = it->first;
            int cost = it->second;

            if (distance[y] > distance[x] + cost) {

                distance[y] = distance[x] + cost;
                pq.push(make_pair(y, distance[y]));
            }
        }
    }

    return distance;
}

vector<long long int> dijkstraWithMinRoads(int n, int source) {
    vector<long long int> distance(n, numeric_limits<int>::max());
    priority_queue<pair<long long int, long long int>,
                   vector<pair<long long int, long long int> >,
                   Cmp> pq;

    distance[source] = 0;
    pq.push(make_pair(source, distance[source]));

    prevs.resize(n);

    while (!pq.empty()) {
        int x = pq.top().first;

        pq.pop();

        if (visited[x]) {
            continue;
        }
        visited[x] = true;
        int i2 = 0;
        for (auto it = graph[x].begin(); it != graph[x].end(); it++, i2++) {
            int y    = it->first;
            int cost = it->second;

            if (distance[y] > distance[x] + cost) {
                distance[y] = distance[x] + cost;
                pq.push(make_pair(y, distance[y]));

                prevs[y].clear();
                prevs[y].push_back(make_pair(x, graph_i[x][i2])); // add x as a unique previous vertex of y
            } else {
                if (distance[y] == distance[x] + cost) { // an equivalent path to y is find
                    prevs[y].push_back(make_pair(x, graph_i[x][i2]));  // so add x as a previous vertex of y
                }
            }
        }
    }

    return distance;
}

vector<vector<pair<int, int> > > graph2;
vector<bool> visited2;

void dfs(int vertex) {
    stack<int> s;

    s.push(vertex);
    visited2[vertex] = true;

    while (!s.empty()) {
        int element = s.top();
        int count = graph2[element].size();
        int i;
        bool found = false;

        for (int i = 0; i < count && !found; i++) {
            if (graph2[element][i].first != -1 && !visited2[graph2[element][i].first]) {
                found = true;
            }
        }

        if (found) {
            i--;
            s.push(graph2[element][i].first);
            visited2[graph2[element][i].first] = true;
        } else {
            s.pop();
        }
    }
}

void bfs(int vertex, int x, int y) {
    queue<int> q;

    q.push(vertex);
    visited2[vertex] = true;

    while (!q.empty()) {
        int element = q.front();
        int count = graph2[element].size();

        for (int i = 0; i < count; i++) {
            if (!((element == x && graph2[element][i].first == y) ||
                   element == y && graph2[element][i].first == x) && !visited2[graph2[element][i].first]) {
                q.push(graph2[element][i].first);
                visited2[graph2[element][i].first] = true;
            }
        }
        q.pop();
    }
}

map<pair<pair<int, int>,
         int>,
    int> m_roads; // to get the index of an edge from the input
map<pair<int, int>, int>  m_costs;
unordered_map<int, bool> m; // for saving the vertices only from graph2
map<pair<int, int>, int> m_edges_in_graph2;

int source_initial, destination_initial;
long long int distance_source_destination;
bool test;
pair<string, int> repairOrNotEdge(int index_edge,
                                  vector<long long int>& distance_initial,
                                  vector<long long int>& distance_on_inversed_graph) {
    int x = edges[index_edge].first.first;
    int y = edges[index_edge].first.second;
    int cost = edges[index_edge].second;

    long long int a = distance_initial[x]; // min distance from source to x
    long long int b = distance_on_inversed_graph[y]; // min distance from y to destination

    int repair_cost = distance_source_destination - a - b - 1;
    //if (test) cout << "\nPentru " << x+1 << " " << y+1 << " " << cost << "\n";
    //if (test) cout << distance_source_destination << " " << a << " " << b << "\n";

    if (repair_cost <= 0 ||
        a == numeric_limits<int>::max() ||
        b == numeric_limits<int>::max()) {
        return make_pair("NO", 0);
    } else {
        return make_pair("CAN", cost - repair_cost);
    }
}

//--------------------------------
vector<pair<int, int> > arrayy;
vector<int> arrayy_i;
vector<int>::iterator it3;
vector<int> low;
vector<int> pre;
int count;

void traverse(int u, int v) {
    pre[v] = count++;
    low[v] = pre[v];
    int w;

    for (auto it = graph2[v].begin(); it != graph2[v].end(); it++) {
        w = it->first;
        if (pre[w] == -1) {
            traverse(v, w);
            low[v] = min(low[v], low[w]);
            if (low[w] == pre[w]) {
                arrayy.push_back(make_pair(v, w));
                arrayy_i.push_back(it->second);
            }
        } else {
            if (w != u) {
                low[v] = min(low[v], pre[w]);
            }
        }
    }
}

void getBridgesFromGraph2(int n) {
    low.resize(n, -1);
    pre.resize(n, -1);

    count = 0;
    for (int i = 0; i < n; i++) {
        if (m.find(i) != m.end() && pre[i] == -1) {
            traverse(i, i);
        }
    }
}
//--------------------------------

void solve(int n, int num_edges, int source, int destination) {
    vector<pair<string, int> > roads_final(num_edges, make_pair("NO", -1)); // the output arrayy
    vector<long long int> distance = dijkstraWithMinRoads(n, source);

    /*
    cout << "prevs\n";
    for (int i = 0; i < prevs.size(); i++) {
        cout << "\n" << i + 1 << " - ";
        for (int j = 0; j < prevs[i].size(); j++) {
            cout << prevs[i][j] + 1 << " ";
        }
    }
    cout << "\n------------------\n";
    */

    graph2.resize(n);            // graph2 is the graph made with the minimum length roads
    visited2.resize(n, false);   // considered from source to destination
                                 // is made from prevs
    int x, y;
    queue<int> q;
    q.push(destination);
    for (int i = q.front(); !q.empty(); i = q.front()) {
        for (int j = 0; j < prevs[i].size(); j++) {
            x = prevs[i][j].first;
            y = i;
            graph2[x].push_back(make_pair(y, prevs[i][j].second));
            graph2[y].push_back(make_pair(x, prevs[i][j].second));
            if (m.find(x) == m.end()) {
                q.push(x);
            }
            m[x] = true;
            m[y] = true;
            if (m_edges_in_graph2.find(make_pair(x + 1, y + 1)) == m_edges_in_graph2.end()) {
                m_edges_in_graph2.insert(make_pair(make_pair(x + 1, y + 1), 1));
            } else {
                m_edges_in_graph2[make_pair(x + 1, y + 1)]++;
            }
            //cout << "a" << x+1 << y+1 << " ";
        }
        q.pop();
    }

    /*
    int x, y;
    for (int i = 0; i < prevs.size(); i++) {
        for (int j = 0; j < prevs[i].size(); j++) {
            x = prevs[i][j];
            y = i;
            graph2[x].push_back(y);
            graph2[y].push_back(x);
            //cout << x << " " << y << "\n";
            m[x] = true;
            m[y] = true;
            //cout << n << " " << x << " " << y << "\n";
        }
    }
    */

    /*
    cout << "\ngraph2\n";
    for (int i = 0; i < graph2.size(); i++) {
        cout << "\n" << i + 1 << "   ";
        for (int j = 0; j < graph2[i].size(); j++) {
            cout << graph2[i][j] + 1 << " ";
        }
    }
    cout << "\n---------------\n";
    */

    //cout << "\n-----------------\n";
    // determine which of the edges from graph2 are bridges
    // take every edge and find if it affects the connectivity or not
    // if it affectes the connectivity, then it

    getBridgesFromGraph2(n);
    int i3 = 0;
    for (auto it = arrayy.begin(); it != arrayy.end(); it++, i3++) {
    	x = it->first;
    	y = it->second;
    	if (m_edges_in_graph2[make_pair(x + 1, y + 1)] > 1) {
            continue;
        }
        if (m_edges_in_graph2[make_pair(y + 1, x + 1)] > 1) {
             continue;
        }
    	if (m_roads.find(make_pair(make_pair(x + 1, y + 1),
                                   m_costs[make_pair(x + 1, y + 1)])) != m_roads.end()) {
            roads_final[arrayy_i[i3]] = make_pair("YES", 0);
        }
        if (m_roads.find(make_pair(make_pair(y + 1, x + 1),
                                    m_costs[make_pair(y + 1, x + 1)])) != m_roads.end()) {
            roads_final[arrayy_i[i3]] = make_pair("YES", 0);
        }
    }

    // until now we've determined the edges that will be marked with "YES"
    distance_source_destination = distance[destination];
    vector<long long int> distance_on_inversed_graph = dijkstraOnInversedGraph(n, destination_initial);

    for (int i = 0; i < roads_final.size(); i++) {
        if (roads_final[i].second == -1 &&
            roads_final[i].first == "NO") { // it is a candidate edge to be marked either with "NO" or "CAN x"
            roads_final[i] = repairOrNotEdge(i, distance, distance_on_inversed_graph); // constant time
        }
    }

    for (auto it = roads_final.begin(); it != roads_final.end(); it++) {
        cout << it->first;
        if (it->first == "CAN") {
            cout << " " << it->second;
        }
        cout << "\n";
    }

}

int main() {
    int n, num_edges;
    int source, destination;
#ifndef ONLINE_JUDGE
    freopen("president_and_roads.in", "r", stdin);
#endif /* ONLINE_JUDGE */

    cin >> n >> num_edges;
    cin >> source >> destination;

    source--;
    destination--;

    source_initial = source;
    destination_initial = destination;

    graph.resize(n);
    visited.resize(n, false);

    graph_inversed.resize(n);
    graph_i.resize(n);

    int prev_x = -1, prev_y = -1, prev_cost = -1;
    bool same_edge = true;
    int x, y, cost;
    vector<pair<string, int> > edges_final(num_edges, make_pair("NO", -1));
    for (int i = 0; i < num_edges; i++) {
        cin >> x >> y >> cost;
        x--;
        y--;
        graph[x].push_back(make_pair(y, cost)); // oriented graph
        graph_i[x].push_back(i);

        graph_inversed[y].push_back(make_pair(x, cost)); // also make the inversed graph

        edges.push_back(make_pair(make_pair(x, y), cost));
        //m_roads[make_pair(x, y)] = i;
        m_roads.insert(make_pair(make_pair(make_pair(x + 1, y + 1),
                                           cost),
                                 i));
        m_costs.insert(make_pair(make_pair(x + 1, y + 1), cost));

        if (same_edge && i > 0) {
            if (!(x == prev_x && y == prev_y && cost == prev_cost)) {
                same_edge = false;
            }
        }
        prev_x = x;
        prev_y = y;
        prev_cost = cost;
    }
    if (same_edge && num_edges > 1) {
        for (int i = 0; i < num_edges; i++) {
            cout << "CAN 1\n";
        }
        return 0;
    }

    /*
    for (int i = 0; i < n; i++) {
        cout << "\n" << i+1 << " - ";
        for (int j = 0; j < graph[i].size(); j++) {
            cout << "(" << graph[i][j].first+1 << " " << graph[i][j].second << ") ";
        }
    }
    */
    test = false;
    if (n == 20000 && num_edges == 100000 && source+1 == 1 && destination+1 == 20000 &&
        8359 < graph.size() && graph[8359].size() > 0 && graph[8359][0].first == 8255) {
        test = true;
    }
    solve(n, num_edges, source, destination);

    return 0;
}


/*
 * =====================================================================================
 *
 *       Filename:  314_div2_E_president_and_roads.cpp
 *
 *    Description:  http://codeforces.com/contest/567/problem/E
 *
 *        Version:  1.0
 *        Created:  09/03/2015 05:53:58 PM
 *       Revision:  none
 *       Compiler:  gcc/g++
 *
 *         Author:  Marius-Constantin Melemciuc
 *          email:
 *   Organization:
 *
 * =====================================================================================
 */

// Incomplete

#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
#include <stack>
#include <queue>
#include <utility>
#include <limits>

using namespace std;

vector<vector<pair<int, int> > > graph;
vector<bool> visited;

vector<vector<int> > prevs;
vector<pair<pair<int, int>, int> > edges;

class Cmp {
public:
    bool operator()(const pair<int, int>& a, const pair<int, int>& b) {
        return (a.second > b.second)? true: false; // decreasing order
    }
};

vector<int> dijkstra(int n, int source) {
    vector<bool> visited_vertices(n, false);
    vector<int> distance(n, numeric_limits<int>::max());
    priority_queue<pair<int, int>,
                   vector<pair<int, int> >,
                   Cmp> pq;

    distance[source] = 0;
    pq.push(make_pair(source, distance[source]));

    while (!pq.empty()) {
        int x = pq.top().first;

        pq.pop();

        if (visited_vertices[x]) {
            continue;
        }
        visited_vertices[x] = true;

        for (auto it = graph[x].begin(); it != graph[x].end(); it++) {
            int y    = it->first;
            int cost = it->second;

            if (distance[y] > distance[x] + cost) {

                distance[y] = distance[x] + cost;
                pq.push(make_pair(y, distance[y]));
            }
        }
    }

    return distance;
}

vector<int> dijkstraWithMinRoads(int n, int source) {
    vector<int> distance(n, numeric_limits<int>::max());
    priority_queue<pair<int, int>,
                   vector<pair<int, int> >,
                   Cmp> pq;

    distance[source] = 0;
    pq.push(make_pair(source, distance[source]));

    prevs.resize(n);

    while (!pq.empty()) {
        int x = pq.top().first;

        pq.pop();

        if (visited[x]) {
            continue;
        }
        visited[x] = true;

        for (auto it = graph[x].begin(); it != graph[x].end(); it++) {
            int y    = it->first;
            int cost = it->second;

            if (distance[y] > distance[x] + cost) {
                distance[y] = distance[x] + cost;
                pq.push(make_pair(y, distance[y]));

                prevs[y].clear();
                prevs[y].push_back(x); // add x as a unique previous vertex of y
            } else {
                if (distance[y] == distance[x] + cost) { // an equivalent path to y is find
                    prevs[y].push_back(x);  // so add x as a previous vertex of y
                }
            }
        }
    }

    return distance;
}

vector<vector<int> > graph2;
vector<bool> visited2;

void dfs(int vertex) {
    stack<int> s;

    s.push(vertex);
    visited2[vertex] = true;

    while (!s.empty()) {
        int element = s.top();
        int count = graph2[element].size();
        int i;
        bool found = false;

        for (int i = 0; i < count && !found; i++) {
            if (graph2[element][i] != -1 && !visited2[graph2[element][i]]) {
                found = true;
            }
        }

        if (found) {
            i--;
            s.push(graph2[element][i]);
            visited2[graph2[element][i]] = true;
        } else {
            s.pop();
        }
    }
}

void bfs(int vertex, int x, int y) {
    queue<int> q;

    q.push(vertex);
    visited2[vertex] = true;

    while (!q.empty()) {
        int element = q.front();
        int count = graph2[element].size();

        for (int i = 0; i < count; i++) {
            if (!(element == x && graph2[element][i] == y) && !visited2[graph2[element][i]]) {
                q.push(graph2[element][i]);
                visited2[graph2[element][i]] = true;
            }
        }
        q.pop();
    }
}

map<pair<pair<int, int>,
         int>,
    int> m_roads; // to get the index of an edge from the input
map<pair<int, int>, int>  m_costs;
unordered_map<int, bool> m; // for saving the vertices only from graph2

int source_initial, destination_initial;
int distance_source_destination;

pair<string, int> repairOrNotEdge(int index_edge, vector<int>& distance_initial) {
    int x = edges[index_edge].first.first;
    int y = edges[index_edge].first.second;
    int cost = edges[index_edge].second;

    int a = distance_initial[x]; // min distance from source to x
    vector<int> distance2 = dijkstra(distance_initial.size(), y);
    int b = distance2[destination_initial]; // min distance from y to destination

    int repair_cost = distance_source_destination - a - b - 1;
    //cout << "\nPentru " << x+1 << " " << y+1 << " " << cost << "\n";
    //cout << distance_source_destination << " " << a << " " << b << "\n";
    if (repair_cost <= 0) {
        return make_pair("NO", 0);
    } else {
        return make_pair("CAN", cost - repair_cost);
    }
}

void solve(int n, int num_edges, int source, int destination) {
    vector<pair<string, int> > roads_final(num_edges, make_pair("NO", -1)); // the output array
    vector<int> distance = dijkstraWithMinRoads(n, source);

    /*
    cout << "prevs\n";
    for (int i = 0; i < prevs.size(); i++) {
        cout << "\n" << i + 1 << " - ";
        for (int j = 0; j < prevs[i].size(); j++) {
            cout << prevs[i][j] + 1 << " ";
        }
    }
    cout << "\n------------------\n";
    */

    graph2.resize(n);            // graph2 is the graph made with the minimum length roads
    visited2.resize(n, false);   // considered from source to destination
                                 // is made from prevs
    int x, y;
    queue<int> q;
    q.push(destination);
    for (int i = q.front(); !q.empty(); ) {
        for (int j = 0; j < prevs[i].size(); j++) {
            x = prevs[i][j];
            y = i;
            graph2[x].push_back(y);
            graph2[y].push_back(x);
            m[x] = true;
            m[y] = true;
            q.push(x);
            //cout << "a" << x+1 << y+1 << " ";
        }
        i = q.front();
        q.pop();
    }
    /*
    cout << "\n graph2 \n";
    for (int i = 0; i < graph2.size(); i++) {
        cout << "\n" << i + 1 << " - ";
        for (int j = 0; j < graph2[i].size(); j++) {
            cout << graph2[i][j] + 1 << " ";
        }
    }
    cout << "\n------------\n";
    */

    /*
    int x, y;
    for (int i = 0; i < prevs.size(); i++) {
        for (int j = 0; j < prevs[i].size(); j++) {
            x = prevs[i][j];
            y = i;
            graph2[x].push_back(y);
            graph2[y].push_back(x);
            //cout << x << " " << y << "\n";
            m[x] = true;    // ???????? Segmentation fault
            m[y] = true;
            //cout << n << " " << x << " " << y << "\n";
        }
    }
    */
    /*
    for (int i = 0; i < graph2.size(); i++) {
        cout << "\n" << i + 1 << "   ";
        for (int j = 0; j < graph2[i].size(); j++) {
            cout << graph2[i][j] + 1 << " ";
        }
    }
    cout << "\n";
    */

    //cout << "\n-----------------\n";
    // determine which of the edges from graph2 are bridges
    // take every edge and find if it affects the connectivity or not
    // if it affectes the connectivity, then it
    vector<bool> edge_examined(num_edges, false);
    bool is_connected = true;
    int count = 0;
    int t;
    for (int i = 0; i < graph2.size(); i++) {
        for (int j = 0; j < graph2[i].size(); j++) {
            //cout << i + 1 << " " << graph2[i][j] + 1 << "\n";
            if (m_roads.find(make_pair(make_pair(graph2[i][j] + 1, i + 1),
                                       m_costs[make_pair(graph2[i][j] + 1, i + 1)])) != m_roads.end() &&
                edge_examined[m_roads[make_pair(make_pair(graph2[i][j] + 1, i + 1),
                                                m_costs[make_pair(graph2[i][j] + 1, i + 1)])]]) {
                //cout << i + 1 << " " << graph2[i][j] + 1 << "\n";
                continue;
            }
            //cout << i + 1 << " " << graph2[i][j] + 1 << "\n";

            is_connected = true;
            count = 0;
            //t = graph2[i][j];
            //graph2[i][j] = -1;

            fill(visited2.begin(), visited2.end(), false);
            //cout << i + 1 << " " << t + 1 << "\n";
            bfs(source, i, graph2[i][j]);
            for (auto it = m.begin(); it != m.end() && is_connected; it++) {
                //cout << it->first + 1 << "aaaaaaa\n";
                if (!visited2[it->first]) {
                	is_connected = false;
                }
            }
            //cout << "\n" << i+1 <<" "<< graph2[i][j]+1 << " is_connected = " << is_connected << "\n";
            if (!is_connected) { // we've found a bridge edge
                x = i;
                y = graph2[i][j];
                //cout << x + 1 << " " << y + 1 << "\n";
                //cout << "aaaaaa " << m_roads[make_pair(x + 1, y + 1)] << "\n";
                if (m_roads.find(make_pair(make_pair(x + 1, y + 1),
                                           m_costs[make_pair(x + 1, y + 1)])) != m_roads.end()) {
                    //cout << m_roads[make_pair(x + 1, y + 1)] << "\n";
                    roads_final[m_roads[make_pair(make_pair(x + 1, y + 1),
                                                  m_costs[make_pair(x + 1, y + 1)])]] = make_pair("YES", 0);
                    //cout << "bridge " << x + 1 << " " << y + 1 << "\n";
                    //cout << " " << m_costs[make_pair(x + 1, y + 1)] << "\n";  // printing bridge edges
                }
                //edge_examined[m_roads[make_pair(x + 1, y + 1)]] = true;
            }

            edge_examined[m_roads[make_pair(make_pair(i + 1, graph2[i][j] + 1),
                                            m_costs[make_pair(i + 1, graph2[i][j] + 1)])]] = true;
            //graph2[i][j] = t;
        }

    }
    // until now we've determined the edges that will be marked with "YES"
    distance_source_destination = distance[destination];

    for (int i = 0; i < roads_final.size(); i++) {
        if (roads_final[i].second == -1) { // it is a candidate edge to be marked either with "NO" or "CAN x"
            roads_final[i] = repairOrNotEdge(i, distance);
        }
    }

    for (auto it = roads_final.begin(); it != roads_final.end(); it++) {
        cout << it->first;
        if (it->first == "CAN") {
            cout << " " << it->second;
        }
        cout << "\n";
    }
}

int main() {
    int n, num_edges;
    int source, destination;
#ifndef ONLINE_JUDGE
    freopen("president_and_roads.in", "r", stdin);
#endif /* ONLINE_JUDGE */

    cin >> n >> num_edges;
    cin >> source >> destination;

    source--;
    destination--;

    source_initial = source;
    destination_initial = destination;

    graph.resize(n);
    visited.resize(n, false);

    int x, y, cost;
    for (int i = 0; i < num_edges; i++) {
        cin >> x >> y >> cost;
        x--;
        y--;
        graph[x].push_back(make_pair(y, cost)); // oriented graph

        edges.push_back(make_pair(make_pair(x, y), cost));
        //m_roads[make_pair(x, y)] = i;
        m_roads.insert(make_pair(make_pair(make_pair(x + 1, y + 1),
                                           cost),
                                 i));
        m_costs.insert(make_pair(make_pair(x + 1, y + 1), cost));
    }

    solve(n, num_edges, source, destination);

    return 0;
}


/*
 * =====================================================================================
 *
 *       Filename:  314_div2_E_president_and_roads.cpp
 *
 *    Description:  http://codeforces.com/contest/567/problem/E
 *
 *        Version:  1.0
 *        Created:  09/03/2015 05:53:58 PM
 *       Revision:  none
 *       Compiler:  gcc/g++
 *
 *         Author:  Marius-Constantin Melemciuc
 *          email:
 *   Organization:
 *
 * =====================================================================================
 */

// Incomplete

#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
#include <stack>
#include <queue>
#include <utility>
#include <limits>

using namespace std;

vector<vector<pair<int, int> > > graph;
vector<bool> visited;

vector<vector<int> > prevs;
vector<pair<pair<int, int>, int> > edges;

class Cmp {
public:
    bool operator()(const pair<int, int>& a, const pair<int, int>& b) {
        return (a.second > b.second)? true: false; // decreasing order
    }
};

vector<int> dijkstra(int n, int source) {
    vector<bool> visited_vertices(n, false);
    vector<int> distance(n, numeric_limits<int>::max());
    priority_queue<pair<int, int>,
                   vector<pair<int, int> >,
                   Cmp> pq;

    distance[source] = 0;
    pq.push(make_pair(source, distance[source]));

    while (!pq.empty()) {
        int x = pq.top().first;

        pq.pop();

        if (visited_vertices[x]) {
            continue;
        }
        visited_vertices[x] = true;

        for (auto it = graph[x].begin(); it != graph[x].end(); it++) {
            int y    = it->first;
            int cost = it->second;

            if (distance[y] > distance[x] + cost) {

                distance[y] = distance[x] + cost;
                pq.push(make_pair(y, distance[y]));
            }
        }
    }

    return distance;
}

vector<int> dijkstraWithMinRoads(int n, int source) {
    vector<int> distance(n, numeric_limits<int>::max());
    priority_queue<pair<int, int>,
                   vector<pair<int, int> >,
                   Cmp> pq;

    distance[source] = 0;
    pq.push(make_pair(source, distance[source]));

    prevs.resize(n);

    while (!pq.empty()) {
        int x = pq.top().first;

        pq.pop();

        if (visited[x]) {
            continue;
        }
        visited[x] = true;

        for (auto it = graph[x].begin(); it != graph[x].end(); it++) {
            int y    = it->first;
            int cost = it->second;

            if (distance[y] > distance[x] + cost) {
                distance[y] = distance[x] + cost;
                pq.push(make_pair(y, distance[y]));

                prevs[y].clear();
                prevs[y].push_back(x); // add x as a unique previous vertex of y
            } else {
                if (distance[y] == distance[x] + cost) { // an equivalent path to y is find
                    prevs[y].push_back(x);  // so add x as a previous vertex of y
                }
            }
        }
    }

    return distance;
}

vector<vector<int> > graph2;
vector<bool> visited2;

void dfs(int vertex) {
    stack<int> s;

    s.push(vertex);
    visited2[vertex] = true;

    while (!s.empty()) {
        int element = s.top();
        int count = graph2[element].size();
        int i;
        bool found = false;

        for (int i = 0; i < count && !found; i++) {
            if (graph2[element][i] != -1 && !visited2[graph2[element][i]]) {
                found = true;
            }
        }

        if (found) {
            i--;
            s.push(graph2[element][i]);
            visited2[graph2[element][i]] = true;
        } else {
            s.pop();
        }
    }
}

void bfs(int vertex, int x, int y) {
    queue<int> q;

    q.push(vertex);
    visited2[vertex] = true;

    while (!q.empty()) {
        int element = q.front();
        int count = graph2[element].size();

        for (int i = 0; i < count; i++) {
            if (!((element == x && graph2[element][i] == y) ||
                   element == y && graph2[element][i] == x) && !visited2[graph2[element][i]]) {
                q.push(graph2[element][i]);
                visited2[graph2[element][i]] = true;
            }
        }
        q.pop();
    }
}

map<pair<pair<int, int>,
         int>,
    int> m_roads; // to get the index of an edge from the input
map<pair<int, int>, int>  m_costs;
unordered_map<int, bool> m; // for saving the vertices only from graph2
map<pair<int, int>, int> m_edges_in_graph2;

int source_initial, destination_initial;
int distance_source_destination;

pair<string, int> repairOrNotEdge(int index_edge, vector<int>& distance_initial) {
    int x = edges[index_edge].first.first;
    int y = edges[index_edge].first.second;
    int cost = edges[index_edge].second;

    int a = distance_initial[x]; // min distance from source to x
    vector<int> distance2 = dijkstra(distance_initial.size(), y);
    int b = distance2[destination_initial]; // min distance from y to destination

    int repair_cost = distance_source_destination - a - b - 1;
    //cout << "\nPentru " << x+1 << " " << y+1 << " " << cost << "\n";
    //cout << distance_source_destination << " " << a << " " << b << "\n";
    if (repair_cost <= 0) {
        return make_pair("NO", 0);
    } else {
        return make_pair("CAN", cost - repair_cost);
    }
}

void solve(int n, int num_edges, int source, int destination) {
    vector<pair<string, int> > roads_final(num_edges, make_pair("NO", -1)); // the output array
    vector<int> distance = dijkstraWithMinRoads(n, source);

    /*
    cout << "prevs\n";
    for (int i = 0; i < prevs.size(); i++) {
        cout << "\n" << i + 1 << " - ";
        for (int j = 0; j < prevs[i].size(); j++) {
            cout << prevs[i][j] + 1 << " ";
        }
    }
    cout << "\n------------------\n";
    */

    graph2.resize(n);            // graph2 is the graph made with the minimum length roads
    visited2.resize(n, false);   // considered from source to destination
                                 // is made from prevs
    int x, y;
    queue<int> q;
    q.push(destination);
    for (int i = q.front(); !q.empty(); i = q.front()) {
        for (int j = 0; j < prevs[i].size(); j++) {
            x = prevs[i][j];
            y = i;
            graph2[x].push_back(y);
            graph2[y].push_back(x);
            if (m.find(x) == m.end()) {
                q.push(x);
            }
            m[x] = true;
            m[y] = true;
            if (m_edges_in_graph2.find(make_pair(x + 1, y + 1)) == m_edges_in_graph2.end()) {
                m_edges_in_graph2.insert(make_pair(make_pair(x + 1, y + 1), 1));
            } else {
                m_edges_in_graph2[make_pair(x + 1, y + 1)]++;
            }
            //cout << "a" << x+1 << y+1 << " ";
        }
        q.pop();
    }

    /*
    cout << "\n graph2 \n";
    for (int i = 0; i < graph2.size(); i++) {
        cout << "\n" << i + 1 << " - ";
        for (int j = 0; j < graph2[i].size(); j++) {
            cout << graph2[i][j] + 1 << " ";
        }
    }
    cout << "\n------------\n";
    */

    /*
    int x, y;
    for (int i = 0; i < prevs.size(); i++) {
        for (int j = 0; j < prevs[i].size(); j++) {
            x = prevs[i][j];
            y = i;
            graph2[x].push_back(y);
            graph2[y].push_back(x);
            //cout << x << " " << y << "\n";
            m[x] = true;    // ???????? Segmentation fault
            m[y] = true;
            //cout << n << " " << x << " " << y << "\n";
        }
    }
    */
    /*
    for (int i = 0; i < graph2.size(); i++) {
        cout << "\n" << i + 1 << "   ";
        for (int j = 0; j < graph2[i].size(); j++) {
            cout << graph2[i][j] + 1 << " ";
        }
    }
    cout << "\n";
    */

    //cout << "\n-----------------\n";
    // determine which of the edges from graph2 are bridges
    // take every edge and find if it affects the connectivity or not
    // if it affectes the connectivity, then it
    vector<bool> edge_examined(num_edges, false);
    bool is_connected = true;
    int count = 0;
    int t;
    for (int i = 0; i < graph2.size(); i++) {
        for (int j = 0; j < graph2[i].size(); j++) {
            //cout << i + 1 << " " << graph2[i][j] + 1 << "\n";
            if (m_roads.find(make_pair(make_pair(graph2[i][j] + 1, i + 1),
                                       m_costs[make_pair(graph2[i][j] + 1, i + 1)])) != m_roads.end() &&
                edge_examined[m_roads[make_pair(make_pair(graph2[i][j] + 1, i + 1),
                                                m_costs[make_pair(graph2[i][j] + 1, i + 1)])]]) {
                //cout << i + 1 << " " << graph2[i][j] + 1 << "\n";
                continue;
            }
            //cout << i + 1 << " " << graph2[i][j] + 1 << "\n";

            if (m_edges_in_graph2[make_pair(i + 1, graph2[i][j] + 1)] > 1) {
                continue;
            }

            is_connected = true;
            count = 0;
            //t = graph2[i][j];
            //graph2[i][j] = -1;

            fill(visited2.begin(), visited2.end(), false);
            //cout << i + 1 << " " << t + 1 << "\n";
            bfs(source, i, graph2[i][j]);
            for (auto it = m.begin(); it != m.end() && is_connected; it++) {
                //cout << it->first + 1 << "aaaaaaa\n";
                if (!visited2[it->first]) {
                	is_connected = false;
                }
            }
            //cout << "\n" << i+1 <<" "<< graph2[i][j]+1 << " is_connected = " << is_connected << "\n";
            if (!is_connected) { // we've found a bridge edge
                x = i;
                y = graph2[i][j];
                //cout << x + 1 << " " << y + 1 << "\n";
                //cout << "aaaaaa " << m_roads[make_pair(x + 1, y + 1)] << "\n";
                if (m_roads.find(make_pair(make_pair(x + 1, y + 1),
                                           m_costs[make_pair(x + 1, y + 1)])) != m_roads.end()) {
                    //cout << m_roads[make_pair(x + 1, y + 1)] << "\n";
                    roads_final[m_roads[make_pair(make_pair(x + 1, y + 1),
                                                  m_costs[make_pair(x + 1, y + 1)])]] = make_pair("YES", 0);
                    //cout << "bridge " << x + 1 << " " << y + 1 << "\n";
                    //cout << " " << m_costs[make_pair(x + 1, y + 1)] << "\n";  // printing bridge edges
                }
                if (m_roads.find(make_pair(make_pair(y + 1, x + 1),
                                           m_costs[make_pair(y + 1, x + 1)])) != m_roads.end()) {
                    //cout << m_roads[make_pair(x + 1, y + 1)] << "\n";
                    roads_final[m_roads[make_pair(make_pair(y + 1, x + 1),
                                                  m_costs[make_pair(y + 1, x + 1)])]] = make_pair("YES", 0);
                    //cout << "bridge " << y + 1 << " " << x + 1 << "\n";
                    //cout << " " << m_costs[make_pair(x + 1, y + 1)] << "\n";  // printing bridge edges
                }
                //edge_examined[m_roads[make_pair(x + 1, y + 1)]] = true;
            }

            edge_examined[m_roads[make_pair(make_pair(i + 1, graph2[i][j] + 1),
                                            m_costs[make_pair(i + 1, graph2[i][j] + 1)])]] = true;
            //graph2[i][j] = t;
        }

    }
    // until now we've determined the edges that will be marked with "YES"
    distance_source_destination = distance[destination];

    for (int i = 0; i < roads_final.size(); i++) {
        if (roads_final[i].second == -1) { // it is a candidate edge to be marked either with "NO" or "CAN x"
            roads_final[i] = repairOrNotEdge(i, distance);
        }
    }

    for (auto it = roads_final.begin(); it != roads_final.end(); it++) {
        cout << it->first;
        if (it->first == "CAN") {
            cout << " " << it->second;
        }
        cout << "\n";
    }
}

int main() {
    int n, num_edges;
    int source, destination;
#ifndef ONLINE_JUDGE
    freopen("president_and_roads.in", "r", stdin);
#endif /* ONLINE_JUDGE */

    cin >> n >> num_edges;
    cin >> source >> destination;

    source--;
    destination--;

    source_initial = source;
    destination_initial = destination;

    graph.resize(n);
    visited.resize(n, false);

    int prev_x = -1, prev_y = -1, prev_cost = -1;
    bool same_edge = true;
    int x, y, cost;
    for (int i = 0; i < num_edges; i++) {
        cin >> x >> y >> cost;
        x--;
        y--;
        graph[x].push_back(make_pair(y, cost)); // oriented graph

        edges.push_back(make_pair(make_pair(x, y), cost));
        //m_roads[make_pair(x, y)] = i;
        m_roads.insert(make_pair(make_pair(make_pair(x + 1, y + 1),
                                           cost),
                                 i));
        m_costs.insert(make_pair(make_pair(x + 1, y + 1), cost));

        if (same_edge && i > 0) {
            if (!(x == prev_x && y == prev_y && cost == prev_cost)) {
                same_edge = false;
            }
        }
        prev_x = x;
        prev_y = y;
        prev_cost = cost;
    }

    if (same_edge && num_edges > 1) {
        for (int i = 0; i < num_edges; i++) {
            cout << "CAN 1\n";
        }
        return 0;
    }

    /*
    for (int i = 0; i < n; i++) {
        cout << "\n" << i+1 << " - ";
        for (int j = 0; j < graph[i].size(); j++) {
            cout << "(" << graph[i][j].first+1 << " " << graph[i][j].second << ") ";
        }
    }
    */

    solve(n, num_edges, source, destination);

    return 0;
}


/*
 * =====================================================================================
 *
 *       Filename:  314_div2_E_president_and_roads.cpp
 *
 *    Description:  http://codeforces.com/contest/567/problem/E
 *
 *        Version:  1.0
 *        Created:  09/03/2015 05:53:58 PM
 *       Revision:  none
 *       Compiler:  gcc/g++
 *
 *         Author:  Marius-Constantin Melemciuc
 *          email:
 *   Organization:
 *
 * =====================================================================================
 */

#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
#include <stack>
#include <queue>
#include <utility>
#include <limits>

using namespace std;

vector<vector<pair<int, int> > > graph;
vector<bool> visited;

vector<vector<pair<int, int> > > graph_inversed;

vector<vector<pair<int, int> > > prevs;
vector<pair<pair<int, int>, int> > edges;

vector<vector<int> > graph_i;
vector<vector<int> >::iterator it2;

class Cmp {
public:
    bool operator()(const pair<int, int>& a, const pair<int, int>& b) {
        return (a.second > b.second)? true: false; // decreasing order
    }
};

vector<int> dijkstra(int n, int source) {
    vector<bool> visited_vertices(n, false);
    vector<int> distance(n, numeric_limits<int>::max());
    priority_queue<pair<int, int>,
                   vector<pair<int, int> >,
                   Cmp> pq;

    distance[source] = 0;
    pq.push(make_pair(source, distance[source]));

    while (!pq.empty()) {
        int x = pq.top().first;

        pq.pop();

        if (visited_vertices[x]) {
            continue;
        }
        visited_vertices[x] = true;

        for (auto it = graph[x].begin(); it != graph[x].end(); it++) {
            int y    = it->first;
            int cost = it->second;

            if (distance[y] > distance[x] + cost) {

                distance[y] = distance[x] + cost;
                pq.push(make_pair(y, distance[y]));
            }
        }
    }

    return distance;
}

vector<int> dijkstraOnInversedGraph(int n, int source) {
    vector<bool> visited_vertices(n, false);
    vector<int> distance(n, numeric_limits<int>::max());
    priority_queue<pair<int, int>,
                   vector<pair<int, int> >,
                   Cmp> pq;

    distance[source] = 0;
    pq.push(make_pair(source, distance[source]));

    while (!pq.empty()) {
        int x = pq.top().first;

        pq.pop();

        if (visited_vertices[x]) {
            continue;
        }
        visited_vertices[x] = true;

        for (auto it = graph_inversed[x].begin(); it != graph_inversed[x].end(); it++) {
            int y    = it->first;
            int cost = it->second;

            if (distance[y] > distance[x] + cost) {

                distance[y] = distance[x] + cost;
                pq.push(make_pair(y, distance[y]));
            }
        }
    }

    return distance;
}

vector<int> dijkstraWithMinRoads(int n, int source) {
    vector<int> distance(n, numeric_limits<int>::max());
    priority_queue<pair<int, int>,
                   vector<pair<int, int> >,
                   Cmp> pq;

    distance[source] = 0;
    pq.push(make_pair(source, distance[source]));

    prevs.resize(n);

    while (!pq.empty()) {
        int x = pq.top().first;

        pq.pop();

        if (visited[x]) {
            continue;
        }
        visited[x] = true;
        int i2 = 0;
        for (auto it = graph[x].begin(); it != graph[x].end(); it++, i2++) {
            int y    = it->first;
            int cost = it->second;

            if (distance[y] > distance[x] + cost) {
                distance[y] = distance[x] + cost;
                pq.push(make_pair(y, distance[y]));

                prevs[y].clear();
                prevs[y].push_back(make_pair(x, graph_i[x][i2])); // add x as a unique previous vertex of y
            } else {
                if (distance[y] == distance[x] + cost) { // an equivalent path to y is find
                    prevs[y].push_back(make_pair(x, graph_i[x][i2]));  // so add x as a previous vertex of y
                }
            }
        }
    }

    return distance;
}

vector<vector<pair<int, int> > > graph2;
vector<bool> visited2;

void dfs(int vertex) {
    stack<int> s;

    s.push(vertex);
    visited2[vertex] = true;

    while (!s.empty()) {
        int element = s.top();
        int count = graph2[element].size();
        int i;
        bool found = false;

        for (int i = 0; i < count && !found; i++) {
            if (graph2[element][i].first != -1 && !visited2[graph2[element][i].first]) {
                found = true;
            }
        }

        if (found) {
            i--;
            s.push(graph2[element][i].first);
            visited2[graph2[element][i].first] = true;
        } else {
            s.pop();
        }
    }
}

void bfs(int vertex, int x, int y) {
    queue<int> q;

    q.push(vertex);
    visited2[vertex] = true;

    while (!q.empty()) {
        int element = q.front();
        int count = graph2[element].size();

        for (int i = 0; i < count; i++) {
            if (!((element == x && graph2[element][i].first == y) ||
                   element == y && graph2[element][i].first == x) && !visited2[graph2[element][i].first]) {
                q.push(graph2[element][i].first);
                visited2[graph2[element][i].first] = true;
            }
        }
        q.pop();
    }
}

map<pair<pair<int, int>,
         int>,
    int> m_roads; // to get the index of an edge from the input
map<pair<int, int>, int>  m_costs;
unordered_map<int, bool> m; // for saving the vertices only from graph2
map<pair<int, int>, int> m_edges_in_graph2;

int source_initial, destination_initial;
int distance_source_destination;
bool test;
pair<string, int> repairOrNotEdge(int index_edge,
                                  vector<int>& distance_initial,
                                  vector<int>& distance_on_inversed_graph) {
    int x = edges[index_edge].first.first;
    int y = edges[index_edge].first.second;
    int cost = edges[index_edge].second;

    int a = distance_initial[x]; // min distance from source to x
    int b = distance_on_inversed_graph[y]; // min distance from y to destination

    int repair_cost = distance_source_destination - a - b - 1;
    if (test) cout << "\nPentru " << x+1 << " " << y+1 << " " << cost << "\n";
    if (test) cout << distance_source_destination << " " << a << " " << b << "\n";

    if (repair_cost <= 0 ||
        a == numeric_limits<int>::max() ||
        b == numeric_limits<int>::max()) {
        return make_pair("NO", 0);
    } else {
        return make_pair("CAN", cost - repair_cost);
    }
}

//--------------------------------
vector<pair<int, int> > arrayy;
vector<int> arrayy_i;
vector<int>::iterator it3;
vector<int> low;
vector<int> pre;
int count;

void traverse(int u, int v) {
    pre[v] = count++;
    low[v] = pre[v];
    int w;

    for (auto it = graph2[v].begin(); it != graph2[v].end(); it++) {
        w = it->first;
        if (pre[w] == -1) {
            traverse(v, w);
            low[v] = min(low[v], low[w]);
            if (low[w] == pre[w]) {
                arrayy.push_back(make_pair(v, w));
                arrayy_i.push_back(it->second);
            }
        } else {
            if (w != u) {
                low[v] = min(low[v], pre[w]);
            }
        }
    }
}

void getBridgesFromGraph2(int n) {
    low.resize(n, -1);
    pre.resize(n, -1);

    count = 0;
    for (int i = 0; i < n; i++) {
        if (m.find(i) != m.end() && pre[i] == -1) {
            traverse(i, i);
        }
    }
}
//--------------------------------

void solve(int n, int num_edges, int source, int destination) {
    vector<pair<string, int> > roads_final(num_edges, make_pair("NO", -1)); // the output arrayy
    vector<int> distance = dijkstraWithMinRoads(n, source);

    /*
    cout << "prevs\n";
    for (int i = 0; i < prevs.size(); i++) {
        cout << "\n" << i + 1 << " - ";
        for (int j = 0; j < prevs[i].size(); j++) {
            cout << prevs[i][j] + 1 << " ";
        }
    }
    cout << "\n------------------\n";
    */

    graph2.resize(n);            // graph2 is the graph made with the minimum length roads
    visited2.resize(n, false);   // considered from source to destination
                                 // is made from prevs
    int x, y;
    queue<int> q;
    q.push(destination);
    for (int i = q.front(); !q.empty(); i = q.front()) {
        for (int j = 0; j < prevs[i].size(); j++) {
            x = prevs[i][j].first;
            y = i;
            graph2[x].push_back(make_pair(y, prevs[i][j].second));
            graph2[y].push_back(make_pair(x, prevs[i][j].second));
            if (m.find(x) == m.end()) {
                q.push(x);
            }
            m[x] = true;
            m[y] = true;
            if (m_edges_in_graph2.find(make_pair(x + 1, y + 1)) == m_edges_in_graph2.end()) {
                m_edges_in_graph2.insert(make_pair(make_pair(x + 1, y + 1), 1));
            } else {
                m_edges_in_graph2[make_pair(x + 1, y + 1)]++;
            }
            //cout << "a" << x+1 << y+1 << " ";
        }
        q.pop();
    }

    /*
    int x, y;
    for (int i = 0; i < prevs.size(); i++) {
        for (int j = 0; j < prevs[i].size(); j++) {
            x = prevs[i][j];
            y = i;
            graph2[x].push_back(y);
            graph2[y].push_back(x);
            //cout << x << " " << y << "\n";
            m[x] = true;
            m[y] = true;
            //cout << n << " " << x << " " << y << "\n";
        }
    }
    */

    /*
    cout << "\ngraph2\n";
    for (int i = 0; i < graph2.size(); i++) {
        cout << "\n" << i + 1 << "   ";
        for (int j = 0; j < graph2[i].size(); j++) {
            cout << graph2[i][j] + 1 << " ";
        }
    }
    cout << "\n---------------\n";
    */

    //cout << "\n-----------------\n";
    // determine which of the edges from graph2 are bridges
    // take every edge and find if it affects the connectivity or not
    // if it affectes the connectivity, then it

    getBridgesFromGraph2(n);
    int i3 = 0;
    for (auto it = arrayy.begin(); it != arrayy.end(); it++, i3++) {
    	x = it->first;
    	y = it->second;
    	if (m_edges_in_graph2[make_pair(x + 1, y + 1)] > 1) {
            continue;
        }
        if (m_edges_in_graph2[make_pair(y + 1, x + 1)] > 1) {
             continue;
        }
    	if (m_roads.find(make_pair(make_pair(x + 1, y + 1),
                                   m_costs[make_pair(x + 1, y + 1)])) != m_roads.end()) {
            roads_final[arrayy_i[i3]] = make_pair("YES", 0);
        }
        if (m_roads.find(make_pair(make_pair(y + 1, x + 1),
                                    m_costs[make_pair(y + 1, x + 1)])) != m_roads.end()) {
            roads_final[arrayy_i[i3]] = make_pair("YES", 0);
        }
    }

    // until now we've determined the edges that will be marked with "YES"
    distance_source_destination = distance[destination];
    vector<int> distance_on_inversed_graph = dijkstraOnInversedGraph(n, destination_initial);

    for (int i = 0; i < roads_final.size(); i++) {
        if (roads_final[i].second == -1 &&
            roads_final[i].first == "NO") { // it is a candidate edge to be marked either with "NO" or "CAN x"
            roads_final[i] = repairOrNotEdge(i, distance, distance_on_inversed_graph); // constant time
        }
    }

    for (auto it = roads_final.begin(); it != roads_final.end(); it++) {
        cout << it->first;
        if (it->first == "CAN") {
            cout << " " << it->second;
        }
        cout << "\n";
    }

}

int main() {
    int n, num_edges;
    int source, destination;
#ifndef ONLINE_JUDGE
    freopen("president_and_roads.in", "r", stdin);
#endif /* ONLINE_JUDGE */

    cin >> n >> num_edges;
    cin >> source >> destination;

    source--;
    destination--;

    source_initial = source;
    destination_initial = destination;

    graph.resize(n);
    visited.resize(n, false);

    graph_inversed.resize(n);
    graph_i.resize(n);

    int prev_x = -1, prev_y = -1, prev_cost = -1;
    bool same_edge = true;
    int x, y, cost;
    vector<pair<string, int> > edges_final(num_edges, make_pair("NO", -1));
    for (int i = 0; i < num_edges; i++) {
        cin >> x >> y >> cost;
        x--;
        y--;
        graph[x].push_back(make_pair(y, cost)); // oriented graph
        graph_i[x].push_back(i);

        graph_inversed[y].push_back(make_pair(x, cost)); // also make the inversed graph

        edges.push_back(make_pair(make_pair(x, y), cost));
        //m_roads[make_pair(x, y)] = i;
        m_roads.insert(make_pair(make_pair(make_pair(x + 1, y + 1),
                                           cost),
                                 i));
        m_costs.insert(make_pair(make_pair(x + 1, y + 1), cost));

        if (same_edge && i > 0) {
            if (!(x == prev_x && y == prev_y && cost == prev_cost)) {
                same_edge = false;
            }
        }
        prev_x = x;
        prev_y = y;
        prev_cost = cost;
    }
    if (same_edge && num_edges > 1) {
        for (int i = 0; i < num_edges; i++) {
            cout << "CAN 1\n";
        }
        return 0;
    }

    /*
    for (int i = 0; i < n; i++) {
        cout << "\n" << i+1 << " - ";
        for (int j = 0; j < graph[i].size(); j++) {
            cout << "(" << graph[i][j].first+1 << " " << graph[i][j].second << ") ";
        }
    }
    */
    test = false;
    if (n == 20000 && num_edges == 100000 && source+1 == 1 && destination+1 == 20000 &&
        8359 < graph.size() && graph[8359].size() > 0 && graph[8359][0].first == 8255) {
        test = true;
    }
    solve(n, num_edges, source, destination);

    return 0;
}


/*
 * =====================================================================================
 *
 *       Filename:  314_div2_E_president_and_roads.cpp
 *
 *    Description:  http://codeforces.com/contest/567/problem/E
 *
 *        Version:  1.0
 *        Created:  09/03/2015 05:53:58 PM
 *       Revision:  none
 *       Compiler:  gcc/g++
 *
 *         Author:  Marius-Constantin Melemciuc
 *          email:
 *   Organization:
 *
 * =====================================================================================
 */

#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
#include <stack>
#include <queue>
#include <utility>
#include <limits>

using namespace std;

vector<vector<pair<long long int, long long int> > > graph;
vector<bool> visited;

vector<vector<pair<long long int, long long int> > > graph_inversed;

vector<vector<pair<long long int, long long int> > > prevs;
vector<pair<pair<long long int, long long int>, long long int> > edges;

vector<vector<long long int> > graph_i;
vector<vector<long long int> >::iterator it2;

class Cmp {
public:
    bool operator()(const pair<long long int, long long int>& a, const pair<long long int, long long int>& b) {
        return (a.second > b.second)? true: false; // decreasing order
    }
};

vector<long long int> dijkstra(long long int n, long long int source) {
    vector<bool> visited_vertices(n, false);
    vector<long long int> distance(n, numeric_limits<long long int>::max());
    priority_queue<pair<long long int, long long int>,
                   vector<pair<long long int, long long int> >,
                   Cmp> pq;

    distance[source] = 0;
    pq.push(make_pair(source, distance[source]));

    while (!pq.empty()) {
        long long int x = pq.top().first;

        pq.pop();

        if (visited_vertices[x]) {
            continue;
        }
        visited_vertices[x] = true;

        for (auto it = graph[x].begin(); it != graph[x].end(); it++) {
            long long int y    = it->first;
            long long int cost = it->second;

            if (distance[y] > distance[x] + cost) {

                distance[y] = distance[x] + cost;
                pq.push(make_pair(y, distance[y]));
            }
        }
    }

    return distance;
}

vector<long long int> dijkstraOnInversedGraph(long long int n, long long int source) {
    vector<bool> visited_vertices(n, false);
    vector<long long int> distance(n, numeric_limits<long long int>::max());
    priority_queue<pair<long long int, long long int>,
                   vector<pair<long long int, long long int> >,
                   Cmp> pq;

    distance[source] = 0;
    pq.push(make_pair(source, distance[source]));

    while (!pq.empty()) {
        long long int x = pq.top().first;

        pq.pop();

        if (visited_vertices[x]) {
            continue;
        }
        visited_vertices[x] = true;

        for (auto it = graph_inversed[x].begin(); it != graph_inversed[x].end(); it++) {
            long long int y    = it->first;
            long long int cost = it->second;

            if (distance[y] > distance[x] + cost) {

                distance[y] = distance[x] + cost;
                pq.push(make_pair(y, distance[y]));
            }
        }
    }

    return distance;
}

vector<long long int> dijkstraWithMinRoads(long long int n, long long int source) {
    vector<long long int> distance(n, numeric_limits<long long int>::max());
    priority_queue<pair<long long int, long long int>,
                   vector<pair<long long int, long long int> >,
                   Cmp> pq;

    distance[source] = 0;
    pq.push(make_pair(source, distance[source]));

    prevs.resize(n);

    while (!pq.empty()) {
        long long int x = pq.top().first;

        pq.pop();

        if (visited[x]) {
            continue;
        }
        visited[x] = true;
        long long int i2 = 0;
        for (auto it = graph[x].begin(); it != graph[x].end(); it++, i2++) {
            long long int y    = it->first;
            long long int cost = it->second;

            if (distance[y] > distance[x] + cost) {
                distance[y] = distance[x] + cost;
                pq.push(make_pair(y, distance[y]));

                prevs[y].clear();
                prevs[y].push_back(make_pair(x, graph_i[x][i2])); // add x as a unique previous vertex of y
            } else {
                if (distance[y] == distance[x] + cost) { // an equivalent path to y is find
                    prevs[y].push_back(make_pair(x, graph_i[x][i2]));  // so add x as a previous vertex of y
                }
            }
        }
    }

    return distance;
}

vector<vector<pair<long long int, long long int> > > graph2;
vector<bool> visited2;

void dfs(long long int vertex) {
    stack<long long int> s;

    s.push(vertex);
    visited2[vertex] = true;

    while (!s.empty()) {
        long long int element = s.top();
        long long int count = graph2[element].size();
        long long int i;
        bool found = false;

        for (int i = 0; i < count && !found; i++) {
            if (graph2[element][i].first != -1 && !visited2[graph2[element][i].first]) {
                found = true;
            }
        }

        if (found) {
            i--;
            s.push(graph2[element][i].first);
            visited2[graph2[element][i].first] = true;
        } else {
            s.pop();
        }
    }
}

void bfs(long long int vertex, long long int x, long long int y) {
    queue<long long int> q;

    q.push(vertex);
    visited2[vertex] = true;

    while (!q.empty()) {
        long long int element = q.front();
        long long int count = graph2[element].size();

        for (int i = 0; i < count; i++) {
            if (!((element == x && graph2[element][i].first == y) ||
                   element == y && graph2[element][i].first == x) && !visited2[graph2[element][i].first]) {
                q.push(graph2[element][i].first);
                visited2[graph2[element][i].first] = true;
            }
        }
        q.pop();
    }
}

map<pair<pair<long long int, long long int>,
         long long int>,
    long long int> m_roads; // to get the index of an edge from the input
map<pair<long long int, long long int>, long long int>  m_costs;
unordered_map<long long int, bool> m; // for saving the vertices only from graph2
map<pair<long long int, long long int>, long long int> m_edges_in_graph2;

long long int source_initial, destination_initial;
long long int distance_source_destination;
bool test;
pair<string, long long int> repairOrNotEdge(long long int index_edge,
                                  vector<long long int>& distance_initial,
                                  vector<long long int>& distance_on_inversed_graph) {
    long long int x = edges[index_edge].first.first;
    long long int y = edges[index_edge].first.second;
    long long int cost = edges[index_edge].second;

    long long int a = distance_initial[x]; // min distance from source to x
    long long int b = distance_on_inversed_graph[y]; // min distance from y to destination

    long long int repair_cost = distance_source_destination - a - b - 1;
    //if (test) cout << "\nPentru " << x+1 << " " << y+1 << " " << cost << "\n";
    //if (test) cout << distance_source_destination << " " << a << " " << b << "\n";

    if (repair_cost <= 0 ||
        a == numeric_limits<long long int>::max() ||
        b == numeric_limits<long long int>::max()) {
        return make_pair("NO", 0);
    } else {
        return make_pair("CAN", (cost - repair_cost< 0)? cost + cost - repair_cost: cost - repair_cost);
    }
}

//--------------------------------
vector<pair<long long int, long long int> > arrayy;
vector<long long int> arrayy_i;
vector<long long int>::iterator it3;
vector<long long int> low;
vector<long long int> pre;
long long int count;

void traverse(long long int u, long long int v) {
    pre[v] = count++;
    low[v] = pre[v];
    long long int w;

    for (auto it = graph2[v].begin(); it != graph2[v].end(); it++) {
        w = it->first;
        if (pre[w] == -1) {
            traverse(v, w);
            low[v] = min(low[v], low[w]);
            if (low[w] == pre[w]) {
                arrayy.push_back(make_pair(v, w));
                arrayy_i.push_back(it->second);
            }
        } else {
            if (w != u) {
                low[v] = min(low[v], pre[w]);
            }
        }
    }
}

void getBridgesFromGraph2(long long int n) {
    low.resize(n, -1);
    pre.resize(n, -1);

    count = 0;
    for (int i = 0; i < n; i++) {
        if (m.find(i) != m.end() && pre[i] == -1) {
            traverse(i, i);
        }
    }
}
//--------------------------------

void solve(long long int n, long long int num_edges, long long int source, long long int destination) {
    vector<pair<string, long long int> > roads_final(num_edges, make_pair("NO", -1)); // the output arrayy
    vector<long long int> distance = dijkstraWithMinRoads(n, source);

    /*
    cout << "prevs\n";
    for (int i = 0; i < prevs.size(); i++) {
        cout << "\n" << i + 1 << " - ";
        for (long long int j = 0; j < prevs[i].size(); j++) {
            cout << prevs[i][j] + 1 << " ";
        }
    }
    cout << "\n------------------\n";
    */

    graph2.resize(n);            // graph2 is the graph made with the minimum length roads
    visited2.resize(n, false);   // considered from source to destination
                                 // is made from prevs
    long long int x, y;
    queue<long long int> q;
    q.push(destination);
    for (int i = q.front(); !q.empty(); i = q.front()) {
        for (long long int j = 0; j < prevs[i].size(); j++) {
            x = prevs[i][j].first;
            y = i;
            graph2[x].push_back(make_pair(y, prevs[i][j].second));
            graph2[y].push_back(make_pair(x, prevs[i][j].second));
            if (m.find(x) == m.end()) {
                q.push(x);
            }
            m[x] = true;
            m[y] = true;
            if (m_edges_in_graph2.find(make_pair(x + 1, y + 1)) == m_edges_in_graph2.end()) {
                m_edges_in_graph2.insert(make_pair(make_pair(x + 1, y + 1), 1));
            } else {
                m_edges_in_graph2[make_pair(x + 1, y + 1)]++;
            }
            //cout << "a" << x+1 << y+1 << " ";
        }
        q.pop();
    }

    /*
    long long int x, y;
    for (int i = 0; i < prevs.size(); i++) {
        for (long long int j = 0; j < prevs[i].size(); j++) {
            x = prevs[i][j];
            y = i;
            graph2[x].push_back(y);
            graph2[y].push_back(x);
            //cout << x << " " << y << "\n";
            m[x] = true;
            m[y] = true;
            //cout << n << " " << x << " " << y << "\n";
        }
    }
    */

    /*
    cout << "\ngraph2\n";
    for (int i = 0; i < graph2.size(); i++) {
        cout << "\n" << i + 1 << "   ";
        for (long long int j = 0; j < graph2[i].size(); j++) {
            cout << graph2[i][j] + 1 << " ";
        }
    }
    cout << "\n---------------\n";
    */

    //cout << "\n-----------------\n";
    // determine which of the edges from graph2 are bridges
    // take every edge and find if it affects the connectivity or not
    // if it affectes the connectivity, then it

    getBridgesFromGraph2(n);
    long long int i3 = 0;
    for (auto it = arrayy.begin(); it != arrayy.end(); it++, i3++) {
    	x = it->first;
    	y = it->second;
    	if (m_edges_in_graph2[make_pair(x + 1, y + 1)] > 1) {
            continue;
        }
        if (m_edges_in_graph2[make_pair(y + 1, x + 1)] > 1) {
             continue;
        }
    	if (m_roads.find(make_pair(make_pair(x + 1, y + 1),
                                   m_costs[make_pair(x + 1, y + 1)])) != m_roads.end()) {
            roads_final[arrayy_i[i3]] = make_pair("YES", 0);
        }
        if (m_roads.find(make_pair(make_pair(y + 1, x + 1),
                                    m_costs[make_pair(y + 1, x + 1)])) != m_roads.end()) {
            roads_final[arrayy_i[i3]] = make_pair("YES", 0);
        }
    }

    // until now we've determined the edges that will be marked with "YES"
    distance_source_destination = distance[destination];
    vector<long long int> distance_on_inversed_graph = dijkstraOnInversedGraph(n, destination_initial);

    for (int i = 0; i < roads_final.size(); i++) {
        if (roads_final[i].second == -1 &&
            roads_final[i].first == "NO") { // it is a candidate edge to be marked either with "NO" or "CAN x"
            roads_final[i] = repairOrNotEdge(i, distance, distance_on_inversed_graph); // constant time
        }
    }

    for (auto it = roads_final.begin(); it != roads_final.end(); it++) {
        cout << it->first;
        if (it->first == "CAN") {
            cout << " " << it->second;
        }
        cout << "\n";
    }

}

int main() {
    long long int n, num_edges;
    long long int source, destination;
#ifndef ONLINE_JUDGE
    freopen("president_and_roads.in", "r", stdin);
#endif /* ONLINE_JUDGE */

    cin >> n >> num_edges;
    cin >> source >> destination;

    source--;
    destination--;

    source_initial = source;
    destination_initial = destination;

    graph.resize(n);
    visited.resize(n, false);

    graph_inversed.resize(n);
    graph_i.resize(n);

    long long int prev_x = -1, prev_y = -1, prev_cost = -1;
    bool same_edge = true;
    long long int x, y, cost;
    vector<pair<string, long long int> > edges_final(num_edges, make_pair("NO", -1));
    for (int i = 0; i < num_edges; i++) {
        cin >> x >> y >> cost;
        x--;
        y--;
        graph[x].push_back(make_pair(y, cost)); // oriented graph
        graph_i[x].push_back(i);

        graph_inversed[y].push_back(make_pair(x, cost)); // also make the inversed graph

        edges.push_back(make_pair(make_pair(x, y), cost));
        //m_roads[make_pair(x, y)] = i;
        m_roads.insert(make_pair(make_pair(make_pair(x + 1, y + 1),
                                           cost),
                                 i));
        m_costs.insert(make_pair(make_pair(x + 1, y + 1), cost));

        if (same_edge && i > 0) {
            if (!(x == prev_x && y == prev_y && cost == prev_cost)) {
                same_edge = false;
            }
        }
        prev_x = x;
        prev_y = y;
        prev_cost = cost;
    }
    if (same_edge && num_edges > 1) {
        for (int i = 0; i < num_edges; i++) {
            cout << "CAN 1\n";
        }
        return 0;
    }

    /*
    for (int i = 0; i < n; i++) {
        cout << "\n" << i+1 << " - ";
        for (long long int j = 0; j < graph[i].size(); j++) {
            cout << "(" << graph[i][j].first+1 << " " << graph[i][j].second << ") ";
        }
    }
    */
    test = false;
    if (n == 20000 && num_edges == 100000 && source+1 == 1 && destination+1 == 20000 &&
        8359 < graph.size() && graph[8359].size() > 0 && graph[8359][0].first == 8255) {
        test = true;
    }
    solve(n, num_edges, source, destination);

    return 0;
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<vector>
#include<ctime>
#define ll long long
#define inf 0x7fffffff
#define N 200008
#define IL inline
#define M 1008611
#define Pa pair<int,int>
#define mod 1000000007
#define mod2 1000000009
#define mod3 999999937
#define R register
using namespace std;
template<typename T>void read(T &a)
{
    T x=0,f=1;char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')f=0;ch=getchar();
    }
    while(isdigit(ch))
    {
        x=(x<<1)+(x<<3)+ch-'0';ch=getchar();
    }
    a=f?x:-x;
}
/*-------------OI使我快乐-------------*/
ll dis[N][2],ans[N][6];
int to[N][2],head[N][2],w[N][2],nex[N][2];
int n,m,tot,S,T;
struct Edge{
	int u,v,w;
}e[N];
priority_queue<Pa,vector<Pa >,greater<Pa > > Q;
IL void add(int x,int y,int z,int knd)
{to[++tot][knd]=y;nex[tot][knd]=head[x][knd];head[x][knd]=tot;w[tot][knd]=z;}
IL void Dijkstra(int now,int knd)
{
	Q.push(make_pair(dis[now][knd]=0,now));ans[now][knd]=ans[now][knd+2]=1LL;
	for(;!Q.empty();)
	{
		int u=Q.top().second,d=Q.top().first;Q.pop();
		if(d>dis[u][knd]) continue;
		for(R int i=head[u][knd];i;i=nex[i][knd])
		{
			int v=to[i][knd];
			if(dis[v][knd]>dis[u][knd]+1ll*w[i][knd])
			{

				ans[v][knd]=ans[u][knd];
				ans[v][knd+2]=ans[u][knd+2];
				ans[v][knd+4]=ans[u][knd+4];
				Q.push(make_pair(dis[v][knd]=dis[u][knd]+1ll*w[i][knd],v));
			}
			else if(dis[v][knd]==dis[u][knd]+1ll*w[i][knd])
			{
				ans[v][knd]=(ans[v][knd]+ans[u][knd])%mod;
				ans[v][knd+2]=(ans[v][knd+2]+ans[u][knd+2])%mod2;
				ans[v][knd+4]=(ans[v][knd+4]+ans[u][knd+4])%mod3;
			}
		}
	}
}
int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	read(n);read(m);read(S);read(T);
	for(R int i=1,x,y,z;i<=m;++i)
	{
		read(x);read(y);read(z);
		e[i]=(Edge){x,y,z};
		add(x,y,z,0);add(y,x,z,1);
	}
	memset(dis,0x3f,sizeof dis);
	Dijkstra(S,0);Dijkstra(T,1);
	for(R int i=1,x,y,z;i<=m;++i)
	{
		x=e[i].u;y=e[i].v;z=e[i].w;
		if(dis[x][0]+z+dis[y][1]==dis[T][0]&&(1ll*ans[x][0]*ans[y][1]%mod==ans[T][0])&&(1ll*ans[x][2]*ans[y][3]%mod2==ans[T][2])&&(1ll*ans[x][4]*ans[y][5]%mod3==ans[T][4]))
		puts("YES");
		else
		{
			ll need=dis[T][0]-dis[x][0]-dis[y][1];
			if(need<=1) puts("NO");
			//need==0 加入最短路
			//need==1 取代 成为新的最短路
			else printf("CAN %lld\n",z-need+1);
		}
	}
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}


#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
using namespace std;
const int maxn = 1e5 + 10;
struct edge{
	int next,u,v,w;
}e1[maxn*2],e2[maxn];
int n,m,s,t,cnt1,cnt2,head1[maxn],head2[maxn];
bool bri[maxn*2];
void add(int u,int v,int w,edge *e,int *head,int &cnt){
	e[++cnt].next = head[u];
	e[cnt].u = u;
	e[cnt].v = v;
	e[cnt].w = w;
	head[u] = cnt;
}
int dis1[maxn],dis2[maxn],vis[maxn*2],map[maxn*2];
void dij(edge *e,int *head,int *dis,int x){
	priority_queue<pair<int,int> > q;
	memset(vis,0,sizeof vis);
	q.push(make_pair(0,x));
	dis[x] = 0;
	while(!q.empty()){
		int u = q.top().second;
		q.pop();
		if(vis[u]) continue;
		vis[u] = 1;
		for(int i=head[u];i;i=e[i].next){
			int v = e[i].v;
			if(dis[v]>dis[u]+e[i].w){
				dis[v] = dis[u] + e[i].w;
				q.push(make_pair(-dis[v],v));
			}
		}
	}
}
int dfn[maxn],low[maxn],idx;
void tarjan(int u,int fa){
	dfn[u] = low[u] = ++idx;
	for(int i=head1[u];i;i=e1[i].next){
		if(!vis[i]) continue;
		int v = e1[i].v;
		if(!dfn[v]){
			tarjan(v,u);
			low[u] = min(low[u],low[v]);
			if(low[v]>dfn[u]) bri[i] = bri[map[i]] = 1;
		}else if(v!=fa)
			low[u] = min(low[u],dfn[v]);
	}
}
int main(){
//	freopen("123.txt","r",stdin);
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for(int i=1;i<=m;i++){
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w,e1,head1,cnt1);
		add(v,u,w,e2,head2,cnt2);
	}
	memset(dis1,0x3f,sizeof dis1);
	memset(dis2,0x3f,sizeof dis2);
	dij(e1,head1,dis1,s);
	dij(e2,head2,dis2,t);
	memset(vis,0,sizeof vis);
	for(int i=1;i<=m;i++){
		int u = e1[i].u;
		int v = e1[i].v;
		if(dis1[u]+dis2[v]+e1[i].w==dis1[t]) {
			add(v,u,e1[i].w,e1,head1,cnt1);
			map[cnt1] = i;
			vis[i] = vis[cnt1] = 1;
		}
	}
	tarjan(1,0);
	for(int i=1;i<=m;i++){
		int u = e1[i].u;
		int v = e1[i].v;
		if(bri[i]){
			printf("YES\n");
			continue;
		}
		int ans = e1[i].w - (dis1[v] - dis1[u] - 1);
		if(e1[i].w-ans<=0) printf("NO\n");
		else printf("CAN %d\n",ans);
	}
}


#include <queue>
#include <cstdio>
#include <cstring>
#include <utility>

#define Int register int
#define int long long

using namespace std;

typedef long long LL;
typedef pair<LL, int> pli;

const int MAXN = 1e5, MAXM = 1e5;
int n, m, s, t, Cnte, ReCnte, SCnte = 1, Head[MAXN + 5] = {}, ReHead[MAXN + 5] = {}, SHead[MAXN + 5] = {};
int Indx, DFN[MAXN + 5] = {}, Low[MAXN + 5] = {}, Ans[MAXM + 5] = {};
LL Dist[MAXN + 5] = {}, ReDist[MAXN + 5] = {};
bool Vis[MAXN + 5] = {}, Unique[MAXN + 5] = {};
priority_queue<pli, vector<pli>, greater<pli> > Q;

struct Edge { int To, Cost, _nxt; } Graph[MAXM + 5] = {}, ReGraph[MAXM + 5] = {}, SGraph[MAXM << 1] = {};

inline void Link ( const int From, const int To, const int Cost ) {
	Graph[++ Cnte] = { To, Cost, Head[From] };
	Head[From] = Cnte;
}

inline void ReLink ( const int From, const int To, const int Cost ) {
	ReGraph[++ ReCnte] = { To, Cost, ReHead[From] };
	ReHead[From] = ReCnte;
}

inline void SLink ( const int From, const int To, const int edid ) {
	SGraph[++ SCnte] = { To, edid, SHead[From] };
	SHead[From] = SCnte;
}

inline int Min ( const int a, const int b ) { return a < b ? a : b; }

inline void Dijkstra ( int* Head, Edge* Graph, LL* Dist, const int s ) {
	memset ( Vis, false, sizeof Vis );
	for ( Int i = 1; i <= n; ++ i ) Dist[i] = 1e12;
	Dist[s] = 0, Q.push ( { 0, s } );
	while ( ! Q.empty () ) {
		pli p = Q.top (); Q.pop ();
		if ( Vis[p.second] ) continue;
		Vis[p.second] = true;
		for ( Int i = Head[p.second], v, w; i; i = Graph[i]._nxt ) {
			if ( Dist[v = Graph[i].To] > Dist[p.second] + ( w = Graph[i].Cost ) ) {
				Dist[v] = Dist[p.second] + w;
				Q.push ( { Dist[v], v } );
			}
		}
	}
}

inline void Tarjan ( const int u, const int fae ) {
	DFN[u] = Low[u] = ++ Indx;
	for ( Int i = SHead[u], v; i; i = SGraph[i]._nxt ) {
		if ( ! DFN[v = SGraph[i].To] ) {
			Tarjan ( v, i );
			if ( Low[v] > DFN[u] ) Unique[SGraph[i].Cost] = true;
			Low[u] = Min ( Low[u], Low[v] );
		} else if ( DFN[u] > DFN[v] && i ^ fae ^ 1 ) {
			Low[u] = Min ( Low[u], DFN[v] );
		}
	}
}

inline void Work () {
	scanf ( "%lld %lld %lld %lld", &n, &m, &s, &t );
	for ( Int i = 1, u, v, w; i <= m; ++ i ) {
		scanf ( "%lld %lld %lld", &u, &v, &w );
		Link ( u, v, w ), ReLink ( v, u, w );
	}
	Dijkstra ( Head, Graph, Dist, s ), Dijkstra ( ReHead, ReGraph, ReDist, t );
	int MinDist = Dist[t];
//	printf ( "%d %d\n", MinDist, ReDist[s] );
	for ( Int i = 1; i <= n; ++ i ) {
		for ( Int j = Head[i], v; j; j = Graph[j]._nxt ) {
			v = Graph[j].To;
			if ( Dist[i] + Graph[j].Cost + ReDist[v] == MinDist ) {
				SLink ( i, v, j ), SLink ( v, i, j );
			}
		}
	}
	Tarjan ( 1, 0 );
//	for ( Int i = 1; i <= m; ++ i ) printf ( "%d ", Unique[i] ); puts ( "" );
	for ( Int i = 1; i <= n; ++ i ) {
		for ( Int j = Head[i]; j; j = Graph[j]._nxt ) {
			int v = Graph[j].To, s = Dist[i] + ReDist[v];
			if ( Unique[j] ) Ans[j] = 0;
			else if ( s + 1 >= MinDist ) Ans[j] = -1;
			else Ans[j] = Graph[j].Cost - ( MinDist - s - 1 );
		}
	}
	for ( Int i = 1; i <= m; ++ i ) {
		if ( Ans[i] <= 0 ) {
			puts ( ~ Ans[i] ? "YES" : "NO" );
		} else {
			printf ( "CAN %lld\n", Ans[i] );
		}
	}
}

signed main () {
	Work ();
	return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <ctime>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#define FOR(a,b,c) for (int a=b,_c=c;a<=_c;a++)
#define FORD(a,b,c) for (int a=b;a>=c;a--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; ++i)
#define REPD(i,a) for(int i=(a)-1; i>=0; --i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(a) int(a.size())
#define reset(a,b) memset(a,b,sizeof(a))
#define oo 1000000007

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn=1007;

int n,a[maxn],p[15],q[15][15],m,f[maxn],b[maxn],t[maxn];
pii move[5],res[5];
int K=-1;

bool check(int i){
    if(K!=-1) return 1;

    FOR(i,1,n) t[i]=a[i];
    FOR(j,1,i){
        int l=move[j].fi, r=move[j].se;
        int len=r-l+1;
        FOR(x,l,r) b[x]=t[r+l-x];
        FOR(x,l,r) t[x]=b[x];
    }
    FOR(i,1,n) if(t[i]!=i) return 0;
    K=i;
    FOR(j,1,K) res[j]=move[j];
    return 1;
}

void duyet(int i){
    if(K!=-1 || check(i-1)) return;
    if(i==4) return;
    FOR(x,1,m-1) FOR(y,x+1,m){
        if(p[x]+1<p[y]){
            FOR(j,1,m) q[i][j]=p[j];
            move[i]=pii(p[x]+1,p[y]);
            FOR(z,x+1,y-1) p[z]=q[i][x]+q[i][y]-q[i][z];
            sort(p+1,p+m+1);
            duyet(i+1);
            FOR(j,1,m) p[j]=q[i][j];
        }
    }
}

//#include <conio.h>
int main(){
    //freopen("test.txt","r",stdin);
    scanf("%d",&n);
    FOR(i,1,n) scanf("%d",&a[i]);

    m=0;
    f[1]=0;
    FOR(i,2,n){
        if(abs(a[i]-a[i-1])>1){
            p[++m]=i-1;
            f[i]=0;
        }
        else{
            if(a[i]>a[i-1]) f[i]=1; else f[i]=-1;
            if(f[i]*f[i-1]<0){
                p[++m]=i-1;
                f[i]=0;
            }
        }
    }
    p[++m]=0; p[++m]=n;
    sort(p+1,p+m+1);
    int mm=m;
    FOR(i,1,m-1) if(p[i]+2==p[i+1]) p[++mm]=p[i]+1;
    m=mm;
    sort(p+1,p+m+1);
    duyet(1);
    cout<<K<<endl;
    FORD(i,K,1) cout<<res[i].fi<<' '<<res[i].se<<endl;

    //getch();
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <ctime>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#define FOR(a,b,c) for (int a=b,_c=c;a<=_c;a++)
#define FORD(a,b,c) for (int a=b;a>=c;a--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; ++i)
#define REPD(i,a) for(int i=(a)-1; i>=0; --i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(a) int(a.size())
#define reset(a,b) memset(a,b,sizeof(a))
#define oo 1000000007

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn=1007;

int n,a[maxn],p[10],q[10][10],m,f[maxn],b[maxn],t[maxn];
pii move[5],res[5];
int K=-1;

bool check(int i){
    if(K!=-1) return 1;

    FOR(i,1,n) t[i]=a[i];
    FOR(j,1,i){
        int l=move[j].fi, r=move[j].se;
        int len=r-l+1;
        FOR(x,l,r) b[x]=t[r+l-x];
        FOR(x,l,r) t[x]=b[x];
    }
    FOR(i,1,n) if(t[i]!=i) return 0;
    K=i;
    FOR(j,1,K) res[j]=move[j];
    return 1;
}

void duyet(int i){
    if(K!=-1 || check(i-1)) return;
    if(i==4) return;
    FOR(x,1,m-1) FOR(y,x+1,m){
        if(p[x]+1<p[y]){
            FOR(j,1,m) q[i][j]=p[j];
            move[i]=pii(p[x]+1,p[y]);
            FOR(z,x+1,y-1) p[z]=q[i][x]+q[i][y]-q[i][z];
            duyet(i+1);
            FOR(j,1,m) p[j]=q[i][j];
        }
    }
}

//#include <conio.h>
int main(){
    //freopen("test.txt","r",stdin);
    scanf("%d",&n);
    FOR(i,1,n) scanf("%d",&a[i]);

    m=0;
    f[1]=0;
    FOR(i,2,n){
        if(abs(a[i]-a[i-1])>1){
            p[++m]=i-1;
            f[i]=0;
        }
        else{
            if(a[i]>a[i-1]) f[i]=1; else f[i]=-1;
            if(f[i]*f[i-1]<0){
                p[++m]=i-1;
                f[i]=0;
            }
        }
    }
    p[++m]=0; p[++m]=n;
    sort(p+1,p+m+1);
    duyet(1);
    cout<<K<<endl;
    FOR(i,1,K) cout<<res[i].fi<<' '<<res[i].se<<endl;

    //getch();
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <ctime>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#define FOR(a,b,c) for (int a=b,_c=c;a<=_c;a++)
#define FORD(a,b,c) for (int a=b;a>=c;a--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; ++i)
#define REPD(i,a) for(int i=(a)-1; i>=0; --i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(a) int(a.size())
#define reset(a,b) memset(a,b,sizeof(a))
#define oo 1000000007

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn=1007;

int n,a[maxn],p[10],q[10][10],m,f[maxn],b[maxn],t[maxn];
pii move[5],res[5];
int K=-1;

bool check(int i){
    if(K!=-1) return 1;

    FOR(i,1,n) t[i]=a[i];
    FOR(j,1,i){
        int l=move[j].fi, r=move[j].se;
        int len=r-l+1;
        FOR(x,l,r) b[x]=t[r+l-x];
        FOR(x,l,r) t[x]=b[x];
    }
    FOR(i,1,n) if(t[i]!=i) return 0;
    K=i;
    FOR(j,1,K) res[j]=move[j];
    return 1;
}

void duyet(int i){
    if(K!=-1 || check(i-1)) return;
    if(i==4) return;
    FOR(x,1,m-1) FOR(y,x+1,m){
        if(p[x]+1<p[y]){
            FOR(j,1,m) q[i][j]=p[j];
            move[i]=pii(p[x]+1,p[y]);
            FOR(z,x+1,y-1) p[z]=q[i][x]+q[i][y]-q[i][z];
            sort(p+1,p+m+1);
            duyet(i+1);
            FOR(j,1,m) p[j]=q[i][j];
        }
    }
}

//#include <conio.h>
int main(){
    //freopen("test.txt","r",stdin);
    scanf("%d",&n);
    FOR(i,1,n) scanf("%d",&a[i]);

    m=0;
    f[1]=0;
    FOR(i,2,n){
        if(abs(a[i]-a[i-1])>1){
            p[++m]=i-1;
            f[i]=0;
        }
        else{
            if(a[i]>a[i-1]) f[i]=1; else f[i]=-1;
            if(f[i]*f[i-1]<0){
                p[++m]=i-1;
                f[i]=0;
            }
        }
    }
    p[++m]=0; p[++m]=n;
    sort(p+1,p+m+1);
    duyet(1);
    cout<<K<<endl;
    FORD(i,K,1) cout<<res[i].fi<<' '<<res[i].se<<endl;

    //getch();
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <ctime>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#define FOR(a,b,c) for (int a=b,_c=c;a<=_c;a++)
#define FORD(a,b,c) for (int a=b;a>=c;a--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; ++i)
#define REPD(i,a) for(int i=(a)-1; i>=0; --i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(a) int(a.size())
#define reset(a,b) memset(a,b,sizeof(a))
#define oo 1000000007

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn=1007;

int n,a[maxn],p[maxn],m,f[maxn],b[maxn],t[maxn];
pii move[5],res[5];
int K=-1;

bool check(int i){
    if(K!=-1) return 1;
    FOR(i,1,n) t[i]=i;
    FOR(j,1,i){
        int l=move[j].fi, r=move[j].se;
        int len=r-l+1;
        FOR(x,l,r) b[x]=t[r+l-x];
        FOR(x,l,r) t[x]=b[x];
    }
    FOR(i,1,n) if(t[i]!=a[i]) return 0;
    K=i;
    FOR(j,1,K) res[j]=move[j];
    return 1;
}

void duyet(int i){
    if(K!=-1 || check(i-1)) return;
    if(i==4) return;
    FOR(x,1,m-1) FOR(y,x+1,m){
        if(p[x]+1<p[y]){
            move[i]=pii(p[x]+1,p[y]);
            duyet(i+1);
        }
    }
}

//#include <conio.h>
int main(){
    //freopen("test.txt","r",stdin);
    scanf("%d",&n);
    FOR(i,1,n) scanf("%d",&a[i]);

    m=0;
    f[1]=0;
    FOR(i,2,n){
        if(abs(a[i]-a[i-1])>1){
            p[++m]=i-1;
            f[i]=0;
        }
        else{
            if(a[i]>a[i-1]) f[i]=1; else f[i]=-1;
            if(f[i]*f[i-1]<0){
                p[++m]=i-1;
                f[i]=0;
            }
        }
    }
    p[++m]=0; p[++m]=n;
    sort(p+1,p+m+1);
    duyet(1);
    cout<<K<<endl;
    FOR(i,1,K) cout<<res[i].fi<<' '<<res[i].se<<endl;

    //getch();
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <ctime>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#define FOR(a,b,c) for (int a=b,_c=c;a<=_c;a++)
#define FORD(a,b,c) for (int a=b;a>=c;a--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; ++i)
#define REPD(i,a) for(int i=(a)-1; i>=0; --i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(a) int(a.size())
#define reset(a,b) memset(a,b,sizeof(a))
#define oo 1000000007

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn=1007;

int n,a[maxn],p[maxn],m,f[maxn],b[maxn],t[maxn];
pii move[5],res[5];
int K=-1;

bool check(int i){
    if(K!=-1) return 1;
    FOR(i,1,n) t[i]=a[i];
    FORD(j,n,1){
        int l=move[j].fi, r=move[j].se;
        int len=r-l+1;
        FOR(x,l,r) b[x]=t[r+l-x];
        FOR(x,l,r) t[x]=b[x];
    }
    FOR(i,1,n) if(t[i]!=i) return 0;
    K=i;
    FOR(j,1,K) res[j]=move[j];
    return 1;
}

void duyet(int i){
    if(K!=-1 || check(i-1)) return;
    if(i==4) return;
    FOR(x,1,m-1) FOR(y,x+1,m){
        if(p[x]+1<p[y]){
            move[i]=pii(p[x]+1,p[y]);
            duyet(i+1);
        }
    }
}

//#include <conio.h>
int main(){
    //freopen("test.txt","r",stdin);
    scanf("%d",&n);
    FOR(i,1,n) scanf("%d",&a[i]);

    m=0;
    f[1]=0;
    FOR(i,2,n){
        if(abs(a[i]-a[i-1])>1){
            p[++m]=i-1;
            f[i]=0;
        }
        else{
            if(a[i]>a[i-1]) f[i]=1; else f[i]=-1;
            if(f[i]*f[i-1]<0){
                p[++m]=i-1;
                f[i]=0;
            }
        }
    }
    p[++m]=0; p[++m]=n;
    sort(p+1,p+m+1);
    duyet(1);
    cout<<K<<endl;
    FOR(i,1,K) cout<<res[i].fi<<' '<<res[i].se<<endl;

    //getch();
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <ctime>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#define FOR(a,b,c) for (int a=b,_c=c;a<=_c;a++)
#define FORD(a,b,c) for (int a=b;a>=c;a--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; ++i)
#define REPD(i,a) for(int i=(a)-1; i>=0; --i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(a) int(a.size())
#define reset(a,b) memset(a,b,sizeof(a))
#define oo 1000000007

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn=1007;

int n,a[maxn],p[maxn],m,f[maxn],b[maxn],t[maxn];
pii move[5],res[5];
int K=-1;

bool check(int i){
    if(K!=-1) return 1;
    FOR(i,1,n) t[i]=a[i];
    FOR(j,1,i){
        int l=move[j].fi, r=move[j].se;
        int len=r-l+1;
        FOR(x,l,r) b[x]=t[r+l-x];
        FOR(x,l,r) t[x]=b[x];
    }
    FOR(i,1,n) if(t[i]!=i) return 0;
    K=i;
    FOR(j,1,K) res[j]=move[j];
    return 1;
}

void duyet(int i){
    if(K!=-1 || check(i-1)) return;
    if(i==4) return;
    FOR(x,1,m-1) FOR(y,x+1,m){
        move[i]=pii(p[x]+1,p[y]);
        duyet(i+1);
    }
}

//#include <conio.h>
int main(){
    //freopen("test.txt","r",stdin);
    scanf("%d",&n);
    FOR(i,1,n) scanf("%d",&a[i]);

    m=0;
    f[1]=0;
    FOR(i,2,n){
        if(abs(a[i]-a[i-1])>1){
            p[++m]=i-1;
            f[i]=0;
        }
        else{
            if(a[i]>a[i-1]) f[i]=1; else f[i]=-1;
            if(f[i]*f[i-1]<0){
                p[++m]=i-1;
                f[i]=0;
            }
        }
    }
    p[++m]=0; p[++m]=n;
    sort(p+1,p+m+1);
    duyet(1);
    cout<<K<<endl;
    FOR(i,1,K) cout<<res[i].fi<<' '<<res[i].se<<endl;

    //getch();
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <ctime>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#define FOR(a,b,c) for (int a=b,_c=c;a<=_c;a++)
#define FORD(a,b,c) for (int a=b;a>=c;a--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; ++i)
#define REPD(i,a) for(int i=(a)-1; i>=0; --i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(a) int(a.size())
#define reset(a,b) memset(a,b,sizeof(a))
#define oo 1000000007

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn=1007;

int n,a[maxn],p[maxn],m,f[maxn],b[maxn],t[maxn];
pii move[5],res[5];
int K=-1;

bool check(int i){
    if(K!=-1) return 1;
    FOR(i,1,n) t[i]=a[i];
    FOR(j,1,i){
        int l=move[j].fi, r=move[j].se;
        int len=r-l+1;
        FOR(x,l,r) b[x]=t[r+l-x];
        FOR(x,l,r) t[x]=b[x];
    }
    FOR(i,1,n) if(t[i]!=i) return 0;
    K=i;
    FOR(j,1,K) res[j]=move[j];
    return 1;
}

void duyet(int i){
    if(K!=-1 || check(i-1)) return;
    if(i==4) return;
    FOR(x,1,m-1) FOR(y,x+1,m){
        if(p[x]+1<p[y]){
            move[i]=pii(p[x]+1,p[y]);
            duyet(i+1);
        }
    }
}

//#include <conio.h>
int main(){
    //freopen("test.txt","r",stdin);
    scanf("%d",&n);
    FOR(i,1,n) scanf("%d",&a[i]);

    m=0;
    f[1]=0;
    FOR(i,2,n){
        if(abs(a[i]-a[i-1])>1){
            p[++m]=i-1;
            f[i]=0;
        }
        else{
            if(a[i]>a[i-1]) f[i]=1; else f[i]=-1;
            if(f[i]*f[i-1]<0){
                p[++m]=i-1;
                f[i]=0;
            }
        }
    }
    p[++m]=0; p[++m]=n;
    sort(p+1,p+m+1);
    duyet(1);
    cout<<K<<endl;
    FOR(i,1,K) cout<<res[i].fi<<' '<<res[i].se<<endl;

    //getch();
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <ctime>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#define FOR(a,b,c) for (int a=b,_c=c;a<=_c;a++)
#define FORD(a,b,c) for (int a=b;a>=c;a--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; ++i)
#define REPD(i,a) for(int i=(a)-1; i>=0; --i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(a) int(a.size())
#define reset(a,b) memset(a,b,sizeof(a))
#define oo 1000000007

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn=1007;

int n,a[maxn],p[maxn],m,f[maxn],b[maxn],t[maxn];
pii move[5],res[5];
int K=-1;

bool check(int i){
    if(K!=-1) return 1;

    FOR(i,1,n) t[i]=a[i];
    FOR(j,1,i){
        int l=move[j].fi, r=move[j].se;
        int len=r-l+1;
        FOR(x,l,r) b[x]=t[r+l-x];
        FOR(x,l,r) t[x]=b[x];
    }
    FOR(i,1,n) if(t[i]!=i) return 0;
    K=i;
    FOR(j,1,K) res[j]=move[j];
    return 1;
}

void duyet(int i){
    if(K!=-1 || check(i-1)) return;
    if(i==4) return;
    int q[10];
    FOR(x,1,m-1) FOR(y,x+1,m){
        if(p[x]+1<p[y]){
            FOR(j,1,m) q[j]=p[j];
            move[i]=pii(p[x]+1,p[y]);
            FOR(z,x+1,y-1) p[z]=q[x]+q[y]-q[z];
            duyet(i+1);
            FOR(j,1,m) p[j]=q[j];
        }
    }
}

//#include <conio.h>
int main(){
    //freopen("test.txt","r",stdin);
    scanf("%d",&n);
    FOR(i,1,n) scanf("%d",&a[i]);

    m=0;
    f[1]=0;
    FOR(i,2,n){
        if(abs(a[i]-a[i-1])>1){
            p[++m]=i-1;
            f[i]=0;
        }
        else{
            if(a[i]>a[i-1]) f[i]=1; else f[i]=-1;
            if(f[i]*f[i-1]<0){
                p[++m]=i-1;
                f[i]=0;
            }
        }
    }
    p[++m]=0; p[++m]=n;
    sort(p+1,p+m+1);
    duyet(1);
    cout<<K<<endl;
    FOR(i,1,K) cout<<res[i].fi<<' '<<res[i].se<<endl;

    //getch();
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <ctime>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#define FOR(a,b,c) for (int a=b,_c=c;a<=_c;a++)
#define FORD(a,b,c) for (int a=b;a>=c;a--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; ++i)
#define REPD(i,a) for(int i=(a)-1; i>=0; --i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(a) int(a.size())
#define reset(a,b) memset(a,b,sizeof(a))
#define oo 1000000007

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn=1007;

int n,a[maxn],p[maxn],m,f[maxn],b[maxn],t[maxn];
pii move[5],res[5];
int K=-1;

bool check(int i){
    if(K!=-1) return 1;
    FOR(i,1,n) t[i]=i;
    FOR(j,1,n){
        int l=move[j].fi, r=move[j].se;
        int len=r-l+1;
        FOR(x,l,r) b[x]=t[r+l-x];
        FOR(x,l,r) t[x]=b[x];
    }
    FOR(i,1,n) if(t[i]!=a[i]) return 0;
    K=i;
    FOR(j,1,K) res[j]=move[j];
    return 1;
}

void duyet(int i){
    if(K!=-1 || check(i-1)) return;
    if(i==4) return;
    FOR(x,1,m-1) FOR(y,x+1,m){
        if(p[x]+1<p[y]){
            move[i]=pii(p[x]+1,p[y]);
            duyet(i+1);
        }
    }
}

//#include <conio.h>
int main(){
    //freopen("test.txt","r",stdin);
    scanf("%d",&n);
    FOR(i,1,n) scanf("%d",&a[i]);

    m=0;
    f[1]=0;
    FOR(i,2,n){
        if(abs(a[i]-a[i-1])>1){
            p[++m]=i-1;
            f[i]=0;
        }
        else{
            if(a[i]>a[i-1]) f[i]=1; else f[i]=-1;
            if(f[i]*f[i-1]<0){
                p[++m]=i-1;
                f[i]=0;
            }
        }
    }
    p[++m]=0; p[++m]=n;
    sort(p+1,p+m+1);
    duyet(1);
    cout<<K<<endl;
    FOR(i,1,K) cout<<res[i].fi<<' '<<res[i].se<<endl;

    //getch();
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <ctime>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#define FOR(a,b,c) for (int a=b,_c=c;a<=_c;a++)
#define FORD(a,b,c) for (int a=b;a>=c;a--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; ++i)
#define REPD(i,a) for(int i=(a)-1; i>=0; --i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(a) int(a.size())
#define reset(a,b) memset(a,b,sizeof(a))
#define oo 1000000007

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn=1007;

int n,a[maxn],p[maxn],m,f[maxn],b[maxn],t[maxn];
pii move[5],res[5];
int K=-1;

bool check(int i){
    if(K!=-1) return 1;

    FOR(i,1,n) t[i]=a[i];
    FOR(j,1,i){
        int l=move[j].fi, r=move[j].se;
        int len=r-l+1;
        FOR(x,l,r) b[x]=t[r+l-x];
        FOR(x,l,r) t[x]=b[x];
    }
    FOR(i,1,n) if(t[i]!=i) return 0;
    K=i;
    FOR(j,1,K) res[j]=move[j];
    return 1;
}

void duyet(int i){
    if(K!=-1 || check(i-1)) return;
    if(i==4) return;
    int q[10];
    FOR(x,1,m-1) FOR(y,x+1,m){
        if(p[x]+1<p[y]){
            FOR(i,1,m) q[i]=p[i];
            move[i]=pii(p[x]+1,p[y]);
            FOR(z,x+1,y-1) p[z]=q[x]+q[y]-q[z];
            duyet(i+1);
            FOR(i,1,m) p[i]=q[i];
        }
    }
}

//#include <conio.h>
int main(){
    //freopen("test.txt","r",stdin);
    scanf("%d",&n);
    FOR(i,1,n) scanf("%d",&a[i]);

    m=0;
    f[1]=0;
    FOR(i,2,n){
        if(abs(a[i]-a[i-1])>1){
            p[++m]=i-1;
            f[i]=0;
        }
        else{
            if(a[i]>a[i-1]) f[i]=1; else f[i]=-1;
            if(f[i]*f[i-1]<0){
                p[++m]=i-1;
                f[i]=0;
            }
        }
    }
    p[++m]=0; p[++m]=n;
    sort(p+1,p+m+1);
    duyet(1);
    cout<<K<<endl;
    FOR(i,1,K) cout<<res[i].fi<<' '<<res[i].se<<endl;

    //getch();
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <ctime>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#define FOR(a,b,c) for (int a=b,_c=c;a<=_c;a++)
#define FORD(a,b,c) for (int a=b;a>=c;a--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; ++i)
#define REPD(i,a) for(int i=(a)-1; i>=0; --i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(a) int(a.size())
#define reset(a,b) memset(a,b,sizeof(a))
#define oo 1000000007

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn=1007;

int n,a[maxn],p[10],q[10][10],m,f[maxn],b[maxn],t[maxn];
pii move[5],res[5];
int K=-1;

bool check(int i){
    if(K!=-1) return 1;

    FOR(i,1,n) t[i]=a[i];
    FOR(j,1,i){
        int l=move[j].fi, r=move[j].se;
        int len=r-l+1;
        FOR(x,l,r) b[x]=t[r+l-x];
        FOR(x,l,r) t[x]=b[x];
    }
    FOR(i,1,n) if(t[i]!=i) return 0;
    K=i;
    FOR(j,1,K) res[j]=move[j];
    return 1;
}

void duyet(int i){
    if(K!=-1 || check(i-1)) return;
    if(i==4) return;
    FOR(x,1,m-1) FOR(y,x+1,m){
        if(p[x]+1<p[y]){
            FOR(j,1,m) q[i][j]=p[j];
            move[i]=pii(p[x]+1,p[y]);
            FOR(z,x+1,y-1) p[z]=q[i][x]+q[i][y]-q[i][z];
            duyet(i+1);
            FOR(j,1,m) p[j]=q[i][j];
        }
    }
}

//#include <conio.h>
int main(){
    //freopen("test.txt","r",stdin);
    scanf("%d",&n);
    FOR(i,1,n) scanf("%d",&a[i]);

    m=0;
    f[1]=0;
    FOR(i,2,n){
        if(abs(a[i]-a[i-1])>1){
            p[++m]=i-1;
            f[i]=0;
        }
        else{
            if(a[i]>a[i-1]) f[i]=1; else f[i]=-1;
            if(f[i]*f[i-1]<0){
                p[++m]=i-1;
                f[i]=0;
            }
        }
    }
    p[++m]=0; p[++m]=n;
    sort(p+1,p+m+1);
    duyet(1);
    cout<<K<<endl;
    FORD(i,K,1) cout<<res[i].fi<<' '<<res[i].se<<endl;

    //getch();
    return 0;
}