#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
const int M = 400005;
const long long INF = 1e17;
int n, m, s, t;
long long Min;
int vis[2][N];
long long d[2][N];
int en;
int head[3][M], no[M], fa[M];
int DFN[M], LOW[M], DN;
int tj[M], FLAG;
struct POS {
  int u;
  long long d;
  bool operator<(const POS& x) const { return d > x.d; }
};
struct node {
  int to, next;
  long long dis;
} edge[3][M];
struct REC {
  int u, v, e;
  long long c;
} rec[M];
void init() {
  en = 0;
  DN = 0;
  memset(head, -1, sizeof(head));
}
void addEdge(int u, int v, long long x, int flag, long long d) {
  if (d != INF) rec[d].u = u, rec[d].v = v, rec[d].c = x, rec[d].e = en;
  edge[flag][en].to = v;
  edge[flag][en].next = head[flag][u];
  edge[flag][en].dis = x;
  head[flag][u] = en++;
}
void addEdgeMD(int u, int v, long long x, int flag, int d) {
  edge[flag][en].to = v;
  edge[flag][en].next = head[flag][u];
  edge[flag][en].dis = x;
  no[en] = d;
  head[flag][u] = en++;
  edge[flag][en].to = u;
  edge[flag][en].next = head[flag][v];
  edge[flag][en].dis = x;
  no[en] = d;
  head[flag][v] = en++;
}
int R[N];
void SPFA(int flag) {
  queue<int> Q;
  for (int i = 1; i <= n; i++) {
    d[flag][i] = INF;
    vis[flag][i] = 0;
    R[i] = 0;
  }
  d[flag][s] = 0;
  vis[flag][s] = 1;
  Q.push(s);
  while (!Q.empty()) {
    int u = Q.front();
    Q.pop();
    vis[flag][u] = 0;
    for (int i = head[flag][u]; i != -1; i = edge[flag][i].next) {
      int v = edge[flag][i].to;
      if (d[flag][u] + edge[flag][i].dis < d[flag][v]) {
        d[flag][v] = d[flag][u] + edge[flag][i].dis;
        if (!vis[flag][v]) {
          R[v]++;
          Q.push(v);
          vis[flag][v] = 1;
        }
      }
    }
  }
}
void Dijkstra(int flag) {
  priority_queue<POS> q;
  for (int i = 1; i <= n; i++) {
    d[flag][i] = INF;
    vis[flag][i] = 0;
  }
  d[flag][s] = 0;
  q.push((POS){s, 0});
  while (!q.empty()) {
    int u = q.top().u;
    q.pop();
    if (vis[flag][u]) continue;
    vis[flag][u] = 1;
    for (int i = head[flag][u]; i != -1; i = edge[flag][i].next) {
      int v = edge[flag][i].to;
      if (d[flag][v] > d[flag][u] + edge[flag][i].dis) {
        d[flag][v] = d[flag][u] + edge[flag][i].dis;
        q.push((POS){v, d[flag][v]});
      }
    }
  }
}
void input() {
  int a, b;
  long long c;
  for (int i = 0; i < m; i++) {
    scanf("%d %d %lld", &a, &b, &c);
    addEdge(a, b, c, 0, i);
    addEdge(b, a, c, 1, INF);
  }
}
void getD() {
  Dijkstra(0);
  swap(s, t);
  Dijkstra(1);
  swap(s, t);
  Min = d[0][t];
}
void tarjan(int u) {
  DFN[u] = LOW[u] = DN++;
  for (int i = head[2][u]; i != -1; i = edge[2][i].next) {
    int v = edge[2][i].to;
    if (!DFN[v]) {
      fa[v] = no[i];
      tarjan(v);
      LOW[u] = min(LOW[u], LOW[v]);
      if (LOW[v] > DFN[u]) tj[fa[v]] = 1;
    } else if (fa[u] != no[i]) {
      LOW[u] = min(LOW[u], DFN[v]);
    }
  }
}
void buildMD() {
  en = 0;
  for (int i = 0; i < m; i++) {
    REC r = rec[i];
    if (d[0][r.u] + d[1][r.v] + r.c == Min) {
      addEdgeMD(r.u, r.v, r.c, 2, i);
    }
  }
}
void solve() {
  for (int i = 0; i < m; i++) {
    REC r = rec[i];
    long long D = d[0][r.u] + d[1][r.v] + r.c;
    if (d[0][r.u] == INF || d[1][r.v] == INF) {
      printf("NO\n");
      continue;
    }
    if (tj[i])
      printf("YES\n");
    else if (D == Min && r.c > 1)
      printf("CAN 1\n");
    else if (D > Min) {
      int temp = D - Min + 1;
      if (r.c <= temp)
        printf("NO\n");
      else
        printf("CAN %d\n", temp);
    } else
      printf("NO\n");
  }
}
int main() {
  while (scanf("%d %d %d %d", &n, &m, &s, &t) == 4) {
    init();
    input();
    getD();
    buildMD();
    tarjan(s);
    solve();
  }
  return 0;
}
