#include <bits/stdc++.h>
using namespace std;
const int MAX = 1e5 + 1;
int n, m, s, t, num[MAX], low[MAX], cnt;
bool availPoint[MAX], availEdge[MAX], availRes[MAX];
struct NodeEdge {
  int u, v;
  long long cost;
};
NodeEdge edge[MAX];
struct NodeHeap {
  int point;
  long long cost;
  NodeHeap(const int& point, const long long& cost)
      : point(point), cost(cost) {}
};
struct cmpHeap {
  bool operator()(const NodeHeap& x, const NodeHeap& y) {
    return x.cost > y.cost;
  }
};
priority_queue<NodeHeap, vector<NodeHeap>, cmpHeap> heap;
struct NodeAdj : public NodeHeap {
  int id;
  NodeAdj(const int& point, const long long& cost, const int& id)
      : NodeHeap(point, cost), id(id) {}
};
vector<NodeAdj> adj[2][MAX];
long long dis[2][MAX], minLen, tmp;
bool moreOne[2][MAX];
void visit(const int& u, const int& idEdge) {
  low[u] = num[u] = ++cnt;
  availPoint[u] = true;
  for (int type = 0; type < 2; ++type)
    for (int i = 0; i < adj[type][u].size(); ++i)
      if (dis[type][u] + adj[type][u][i].cost +
              dis[1 - type][adj[type][u][i].point] ==
          minLen)
        if (!availEdge[adj[type][u][i].id]) {
          availEdge[adj[type][u][i].id] = true;
          if (availPoint[adj[type][u][i].point])
            low[u] = min(low[u], num[adj[type][u][i].point]);
          else {
            visit(adj[type][u][i].point, adj[type][u][i].id);
            low[u] = min(low[u], low[adj[type][u][i].point]);
          }
        }
  if (idEdge && low[u] >= num[u]) availRes[idEdge] = true;
}
int main() {
  ios_base::sync_with_stdio(0);
  cin >> n >> m >> s >> t;
  for (int i = 1; i <= m; ++i) {
    cin >> edge[i].u >> edge[i].v >> edge[i].cost;
    adj[0][edge[i].u].push_back(NodeAdj(edge[i].v, edge[i].cost, i));
    adj[1][edge[i].v].push_back(NodeAdj(edge[i].u, edge[i].cost, i));
  }
  for (int i = 1; i <= n; ++i)
    if (i != s) dis[0][i] = 1e18;
  for (int i = 1; i <= n; ++i)
    if (i != t) dis[1][i] = 1e18;
  memset(availPoint + 1, false, n);
  heap.push(NodeHeap(s, 0));
  while (!heap.empty()) {
    NodeHeap u = heap.top();
    heap.pop();
    if (availPoint[u.point]) {
      if (u.cost == dis[0][u.point]) moreOne[0][u.point] = true;
      continue;
    }
    availPoint[u.point] = true;
    dis[0][u.point] = u.cost;
    for (int i = 0; i < adj[0][u.point].size(); ++i)
      heap.push(
          NodeHeap(adj[0][u.point][i].point, u.cost + adj[0][u.point][i].cost));
  }
  minLen = dis[0][t];
  memset(availPoint + 1, false, n);
  heap.push(NodeHeap(t, 0));
  while (!heap.empty()) {
    NodeHeap u = heap.top();
    heap.pop();
    if (availPoint[u.point]) {
      if (u.cost == dis[1][u.point]) moreOne[1][u.point] = true;
      continue;
    }
    availPoint[u.point] = true;
    dis[1][u.point] = u.cost;
    for (int i = 0; i < adj[1][u.point].size(); ++i)
      heap.push(
          NodeHeap(adj[1][u.point][i].point, u.cost + adj[1][u.point][i].cost));
  }
  memset(availPoint + 1, false, n);
  visit(s, 0);
  for (int i = 1; i <= m; ++i)
    if (availRes[i])
      cout << "YES\n";
    else {
      tmp = dis[0][edge[i].u] + edge[i].cost + dis[1][edge[i].v] - (minLen - 1);
      if (edge[i].cost > tmp)
        cout << "CAN " << tmp << endl;
      else
        cout << "NO\n";
    }
  return 0;
}
