#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<map>
#include<set>
#include<queue>
#define pb push_back
#define debug puts("=====================");
#define INF (1ll << 60)
using namespace std;
typedef long long ll;
const int N = 1e5 + 100;
int n, m, s, t, ans[N];
struct node {
    int u, v, nxt, l;
} e[N], re[N];
int g[N], rg[N], cnt, rcnt;
void add(int u, int v, int l, int &cnt, int * g, node * e) {
    e[++cnt].u = u;
    e[cnt].v = v;
    e[cnt].l = l;
    e[cnt].nxt = g[u];
    g[u] = cnt;
}
ll dist[N], rdist[N];
int vis[N];
queue<int> q;
void spfa(int st, int ed, ll * dist, int * g, node *e) {
    memset(vis, 0, sizeof(int) * (n + 10));
    vis[st] = 1;
    q.push(st);
    for (int i = 1; i <= n; i++) dist[i] = INF;
    dist[st] = 0;
    int u, v, l;
    while(!q.empty()) {
        u = q.front(); q.pop();
        vis[u] = 0;
        for (int i = g[u]; i; i = e[i].nxt) {
            v = e[i].v, l = e[i].l;
            if (dist[u] + l < dist[v]) {
                dist[v] = dist[u] + l;
                if (!vis[v]) vis[v] = 1, q.push(v);
            }
        }
    }
}
node E[N * 2];
int G[N], cc = 1;
void init_add(int u, int v, int id) {
    E[++cc].u = u;
    E[cc].v = v;
    E[cc].l = id;
    E[cc].nxt = G[u];
    G[u] = cc;

    E[++cc].u = v;
    E[cc].v = u;
    E[cc].l = id;
    E[cc].nxt = G[v];
    G[v] = cc;
}
void init_graph() {
    int u, v, l;
    for (int i = 1; i <= m; i++) {
        u = e[i].u, v = e[i].v, l = e[i].l;
        if (dist[u] + l + rdist[v] == dist[t]) init_add(u, v, i); //, cout<<i<<endl;
    }
    //for (int i = 1; i <= cc; i++) cout<<E[i].u<<" "<<E[i].v<<" "<<E[i].l<<endl;
}

int dfs_clock = 0, dfn[N] = {0}, low[N] = {0};
bool VIS[N * 2] = {0};
void dfs(int u) {
    dfn[u] = low[u] = ++dfs_clock;
    for (int i = G[u]; i; i = E[i].nxt) {
        int v = E[i].v;
        if (!dfn[v]) {
            VIS[i] = VIS[i ^ 1] = true;
            dfs(v);
            low[u] = min(low[v], low[u]);
            if (low[v] > dfn[u]) ans[E[i].l] = -1;
        } else if (dfn[v] < dfn[u] && !VIS[i]) {
            VIS[i] = VIS[i ^ 1] = true;
            low[u] = min(low[u], dfn[v]);
        }
    }
}

void work_yes() {
    for (int i = 1; i <= n; i++) if (!dfn[i]) dfs(i);
}
int main () {
    scanf("%d%d%d%d", &n, &m, &s, &t);
    int u, v, l;
    for (int i = 0; i < m; i++) {
        scanf("%d%d%d", &u, &v, &l);
        add(u, v, l, cnt, g, e);
        add(v, u, l, rcnt, rg, re);
    }
    //for (int i = 1; i <= m; i++) cout<<e[i].u<<" "<<e[i].v<<" "<<e[i].l<<endl;
    //for (int i = 1; i <= m; i++) cout<<re[i].u<<" "<<re[i].v<<" "<<re[i].l<<endl;
    spfa(s, t, dist, g, e);
    spfa(t, s, rdist, rg, re);
    init_graph();
    work_yes();
    for (int i = 1; i <= m; i++) {
        if (ans[i] == -1) puts("YES");
        else {
            u = e[i].u, v = e[i].v, l = e[i].l;
            ll tmp = dist[t] - 1 - dist[u] - rdist[v];
            if (0 < tmp && tmp < l) printf("CAN %d\n", l - tmp);
            else puts("NO");
        }
    }
    return 0;
}


#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<map>
#include<set>
#include<queue>
#define pb push_back
#define debug puts("=====================");
#define INF (1 << 30)
using namespace std;
const int N = 1e5 + 100;
int n, m, s, t, ans[N];
struct node {
    int u, v, nxt, l;
} e[N], re[N];
int g[N], rg[N], cnt, rcnt;
void add(int u, int v, int l, int &cnt, int * g, node * e) {
    e[++cnt].u = u;
    e[cnt].v = v;
    e[cnt].l = l;
    e[cnt].nxt = g[u];
    g[u] = cnt;
}
int dist[N], rdist[N], vis[N];
queue<int> q;
void spfa(int st, int ed, int * dist, int * g, node *e) {
    memset(vis, 0, sizeof(int) * (n + 10));
    vis[st] = 1;
    q.push(st);
    for (int i = 1; i <= n; i++) dist[i] = INF;
    dist[st] = 0;
    int u, v, l;
    while(!q.empty()) {
        u = q.front(); q.pop();
        vis[u] = 0;
        for (int i = g[u]; i; i = e[i].nxt) {
            v = e[i].v, l = e[i].l;
            if (dist[u] + l < dist[v]) {
                dist[v] = dist[u] + l;
                if (!vis[v]) vis[v] = 1, q.push(v);
            }
        }
    }
}
node E[N];
int G[N], cc = 1;
void init_add(int u, int v, int id) {
    E[++cc].u = u;
    E[cc].v = v;
    E[cc].l = id;
    E[cc].nxt = G[u];
    G[u] = cc;

    E[++cc].u = v;
    E[cc].v = u;
    E[cc].l = id;
    E[cc].nxt = G[v];
    G[v] = cc;
}
void init_graph() {
    int u, v, l;
    for (int i = 1; i <= m; i++) {
        u = e[i].u, v = e[i].v, l = e[i].l;
        if (dist[u] + l == dist[v] && rdist[v] + dist[v] == dist[t]) init_add(u, v, i); //, cout<<i<<endl;
    }
    //for (int i = 1; i <= cc; i++) cout<<E[i].u<<" "<<E[i].v<<" "<<E[i].l<<endl;
}

int dfs_clock = 0, dfn[N] = {0}, low[N] = {0};
bool VIS[N] = {0};
void dfs(int u) {
    dfn[u] = low[u] = ++dfs_clock;
    for (int i = G[u]; i; i = E[i].nxt) {
        int v = E[i].v;
        if (!dfn[v]) {
            VIS[i] = VIS[i ^ 1] = true;
            dfs(v);
            low[u] = min(low[v], low[u]);
            if (low[v] > dfn[u]) ans[E[i].l] = -1;
        } else if (dfn[v] < dfn[u] && !VIS[i]) {
            VIS[i] = VIS[i ^ 1] = true;
            low[u] = min(low[u], dfn[v]);
        }
    }
}

void work_yes() {
    for (int i = 1; i <= n; i++) if (!dfn[i]) dfs(i);
}
int main () {
    scanf("%d%d%d%d", &n, &m, &s, &t);
    int u, v, l;
    for (int i = 0; i < m; i++) {
        scanf("%d%d%d", &u, &v, &l);
        add(u, v, l, cnt, g, e);
        add(v, u, l, rcnt, rg, re);
    }
    //for (int i = 1; i <= m; i++) cout<<e[i].u<<" "<<e[i].v<<" "<<e[i].l<<endl;
    //for (int i = 1; i <= m; i++) cout<<re[i].u<<" "<<re[i].v<<" "<<re[i].l<<endl;
    spfa(s, t, dist, g, e);
    spfa(t, s, rdist, rg, re);
    init_graph();
    work_yes();
    for (int i = 1; i <= m; i++) {
        if (ans[i] == -1) puts("YES");
        else {
            u = e[i].u, v = e[i].v, l = e[i].l;
            int tmp = dist[t] - 1 - dist[u] - rdist[v];
            if (0 < tmp && tmp < l) printf("CAN %d\n", l - tmp);
            else puts("NO");
        }
    }
    return 0;
}


#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<map>
#include<set>
#include<queue>
#define pb push_back
#define debug puts("=====================");
#define INF (1 << 30)
using namespace std;
const int N = 1e5 + 100;
int n, m, s, t, ans[N];
struct node {
    int u, v, nxt, l;
} e[N], re[N];
int g[N], rg[N], cnt, rcnt;
void add(int u, int v, int l, int &cnt, int * g, node * e) {
    e[++cnt].u = u;
    e[cnt].v = v;
    e[cnt].l = l;
    e[cnt].nxt = g[u];
    g[u] = cnt;
}
int dist[N], rdist[N], vis[N];
queue<int> q;
void spfa(int st, int ed, int * dist, int * g, node *e) {
    memset(vis, 0, sizeof(int) * (n + 10));
    vis[st] = 1;
    q.push(st);
    for (int i = 1; i <= n; i++) dist[i] = INF;
    dist[st] = 0;
    int u, v, l;
    while(!q.empty()) {
        u = q.front(); q.pop();
        vis[u] = 0;
        for (int i = g[u]; i; i = e[i].nxt) {
            v = e[i].v, l = e[i].l;
            if (dist[u] + l < dist[v]) {
                dist[v] = dist[u] + l;
                if (!vis[v]) vis[v] = 1, q.push(v);
            }
        }
    }
}
node E[N * 2];
int G[N], cc = 1;
void init_add(int u, int v, int id) {
    E[++cc].u = u;
    E[cc].v = v;
    E[cc].l = id;
    E[cc].nxt = G[u];
    G[u] = cc;

    E[++cc].u = v;
    E[cc].v = u;
    E[cc].l = id;
    E[cc].nxt = G[v];
    G[v] = cc;
}
void init_graph() {
    int u, v, l;
    for (int i = 1; i <= m; i++) {
        u = e[i].u, v = e[i].v, l = e[i].l;
        if (dist[u] + l == dist[v] && rdist[v] + dist[v] == dist[t]) init_add(u, v, i); //, cout<<i<<endl;
    }
    //for (int i = 1; i <= cc; i++) cout<<E[i].u<<" "<<E[i].v<<" "<<E[i].l<<endl;
}

int dfs_clock = 0, dfn[N] = {0}, low[N] = {0};
bool VIS[N] = {0};
void dfs(int u) {
    dfn[u] = low[u] = ++dfs_clock;
    for (int i = G[u]; i; i = E[i].nxt) {
        int v = E[i].v;
        if (!dfn[v]) {
            VIS[i] = VIS[i ^ 1] = true;
            dfs(v);
            low[u] = min(low[v], low[u]);
            if (low[v] > dfn[u]) ans[E[i].l] = -1;
        } else if (dfn[v] < dfn[u] && !VIS[i]) {
            VIS[i] = VIS[i ^ 1] = true;
            low[u] = min(low[u], dfn[v]);
        }
    }
}

void work_yes() {
    for (int i = 1; i <= n; i++) if (!dfn[i]) dfs(i);
}
int main () {
    scanf("%d%d%d%d", &n, &m, &s, &t);
    int u, v, l;
    for (int i = 0; i < m; i++) {
        scanf("%d%d%d", &u, &v, &l);
        add(u, v, l, cnt, g, e);
        add(v, u, l, rcnt, rg, re);
    }
    //for (int i = 1; i <= m; i++) cout<<e[i].u<<" "<<e[i].v<<" "<<e[i].l<<endl;
    //for (int i = 1; i <= m; i++) cout<<re[i].u<<" "<<re[i].v<<" "<<re[i].l<<endl;
    spfa(s, t, dist, g, e);
    spfa(t, s, rdist, rg, re);
    init_graph();
    work_yes();
    for (int i = 1; i <= m; i++) {
        if (ans[i] == -1) puts("YES");
        else {
            u = e[i].u, v = e[i].v, l = e[i].l;
            int tmp = dist[t] - 1 - dist[u] - rdist[v];
            if (0 < tmp && tmp < l) printf("CAN %d\n", l - tmp);
            else puts("NO");
        }
    }
    return 0;
}


#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<map>
#include<set>
#include<queue>
#define pb push_back
#define debug puts("=====================");
#define INF (1 << 30)
using namespace std;
const int N = 1e5 + 100;
int n, m, s, t, ans[N];
struct node {
    int u, v, nxt, l;
} e[N], re[N];
int g[N], rg[N], cnt, rcnt;
void add(int u, int v, int l, int &cnt, int * g, node * e) {
    e[++cnt].u = u;
    e[cnt].v = v;
    e[cnt].l = l;
    e[cnt].nxt = g[u];
    g[u] = cnt;
}
int dist[N], rdist[N], vis[N];
queue<int> q;
void spfa(int st, int ed, int * dist, int * g, node *e) {
    memset(vis, 0, sizeof(int) * (n + 10));
    vis[st] = 1;
    q.push(st);
    for (int i = 1; i <= n; i++) dist[i] = INF;
    dist[st] = 0;
    int u, v, l;
    while(!q.empty()) {
        u = q.front(); q.pop();
        vis[u] = 0;
        for (int i = g[u]; i; i = e[i].nxt) {
            v = e[i].v, l = e[i].l;
            if (dist[u] + l < dist[v]) {
                dist[v] = dist[u] + l;
                if (!vis[v]) vis[v] = 1, q.push(v);
            }
        }
    }
}
node E[N * 2];
int G[N], cc = 1;
void init_add(int u, int v, int id) {
    E[++cc].u = u;
    E[cc].v = v;
    E[cc].l = id;
    E[cc].nxt = G[u];
    G[u] = cc;

    E[++cc].u = v;
    E[cc].v = u;
    E[cc].l = id;
    E[cc].nxt = G[v];
    G[v] = cc;
}
void init_graph() {
    int u, v, l;
    for (int i = 1; i <= m; i++) {
        u = e[i].u, v = e[i].v, l = e[i].l;
        if (dist[u] + l + rdist[v] == dist[t]) init_add(u, v, i); //, cout<<i<<endl;
    }
    //for (int i = 1; i <= cc; i++) cout<<E[i].u<<" "<<E[i].v<<" "<<E[i].l<<endl;
}

int dfs_clock = 0, dfn[N] = {0}, low[N] = {0};
bool VIS[N] = {0};
void dfs(int u) {
    dfn[u] = low[u] = ++dfs_clock;
    for (int i = G[u]; i; i = E[i].nxt) {
        int v = E[i].v;
        if (!dfn[v]) {
            VIS[i] = VIS[i ^ 1] = true;
            dfs(v);
            low[u] = min(low[v], low[u]);
            if (low[v] > dfn[u]) ans[E[i].l] = -1;
        } else if (dfn[v] < dfn[u] && !VIS[i]) {
            VIS[i] = VIS[i ^ 1] = true;
            low[u] = min(low[u], dfn[v]);
        }
    }
}

void work_yes() {
    for (int i = 1; i <= n; i++) if (!dfn[i]) dfs(i);
}
int main () {
    scanf("%d%d%d%d", &n, &m, &s, &t);
    int u, v, l;
    for (int i = 0; i < m; i++) {
        scanf("%d%d%d", &u, &v, &l);
        add(u, v, l, cnt, g, e);
        add(v, u, l, rcnt, rg, re);
    }
    //for (int i = 1; i <= m; i++) cout<<e[i].u<<" "<<e[i].v<<" "<<e[i].l<<endl;
    //for (int i = 1; i <= m; i++) cout<<re[i].u<<" "<<re[i].v<<" "<<re[i].l<<endl;
    spfa(s, t, dist, g, e);
    spfa(t, s, rdist, rg, re);
    init_graph();
    work_yes();
    for (int i = 1; i <= m; i++) {
        if (ans[i] == -1) puts("YES");
        else {
            u = e[i].u, v = e[i].v, l = e[i].l;
            int tmp = dist[t] - 1 - dist[u] - rdist[v];
            if (0 < tmp && tmp < l) printf("CAN %d\n", l - tmp);
            else puts("NO");
        }
    }
    return 0;
}


#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <functional>
#include <utility>

#define MP make_pair
#define PB push_back

using namespace std;

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

const ll MOD = 1000*1000*1000+9;

int n, m, s, t;

ll lg_edge[100001];
vector<pii> ls_edges;
vector<pii> v[100001][2];

ll d[100001][2];    //[0]: début, [1]: fin
ll memo_shortest[100001][2];

ll nb_shortest(int u, int dest)
{
    if(memo_shortest[u][dest] != -1)
        return memo_shortest[u][dest];

    const int k = 1-dest;   //si on veut aller à s, on prend les arêtes renversées

    memo_shortest[u][dest] = 0;
    for(int i = 0; i < (int)v[u][k].size(); i++)
        if(d[u][dest] == d[v[u][k][i].first][dest]+v[u][k][i].second)  //passe par le SP
            memo_shortest[u][dest] = (memo_shortest[u][dest]+nb_shortest(v[u][k][i].first, dest))%MOD;

    return memo_shortest[u][dest];
}

int main()
{
    scanf("%d%d%d%d", &n, &m, &s, &t);
    for(int i = 0; i < m; i++)
    {
        int a, b, l;
        scanf("%d%d%d", &a, &b, &l);
        ls_edges.PB(MP(a, b));
        lg_edge[i] = l;
        v[a][0].PB(MP(b, l));
        v[b][1].PB(MP(a, l));
    }

    //Dijkstra, shortest paths
    for(int i = 1; i <= n; i++)
        d[i][0] = d[i][1] = -1;

    priority_queue<pli, vector<pli>, greater<pli> > pq;
    for(int k = 0; k < 2; k++)
    {
        pq.push(MP(0, (k == 0)?s:t));
        while(!pq.empty())
        {
            const ll d_act = pq.top().first;
            const int x_act = pq.top().second;
            pq.pop();

            if(d[x_act][k] == -1)
            {
                d[x_act][k] = d_act;
                for(int i = 0; i < (int)v[x_act][k].size(); i++)
                    if(d[v[x_act][k][i].first][k] == -1)
                        pq.push(MP(d_act+v[x_act][k][i].second, v[x_act][k][i].first));
            }
        }
    }

    for(int i = 1; i <= n; i++)
        memo_shortest[i][0] = memo_shortest[i][1] = -1;

    memo_shortest[s][0] = memo_shortest[t][1] = 1;

    const ll nb_SP = nb_shortest(s, 1);
    const ll lg_trajet = d[s][1];

    for(int i = 0; i < m; i++)
    {
        if((d[ls_edges[i].first][0] == -1) || (d[ls_edges[i].second][1] == -1))
            printf("NO\n");
        else if(((nb_shortest(ls_edges[i].first, 0)*nb_shortest(ls_edges[i].second, 1))%MOD == nb_SP)
            && (lg_trajet == d[ls_edges[i].first][0]+lg_edge[i]+d[ls_edges[i].second][1]))
            printf("YES\n");
        else
        {
            ll nouv_lg = lg_trajet - d[ls_edges[i].first][0] - d[ls_edges[i].second][1] - 1;
            if(nouv_lg < 1)
                printf("NO\n");
            else
                printf("CAN %I64d\n", lg_edge[i]-nouv_lg);
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <functional>
#include <utility>

#define MP make_pair
#define PB push_back

using namespace std;

typedef pair<int, int> pii;

typedef long long ll;
const ll MOD = 1000*1000*1000+9;

int n, m, s, t;

ll lg_edge[100001];
vector<pii> ls_edges;
vector<pii> v[100001];

ll d[100001][2];    //[0]: début, [1]: fin
ll memo_shortest[100001][2];

ll nb_shortest(int u, int dest)
{
    if(memo_shortest[u][dest] != -1)
        return memo_shortest[u][dest];

    memo_shortest[u][dest] = 0;
    for(int i = 0; i < (int)v[u].size(); i++)
        if(d[u][dest] == d[v[u][i].first][dest]+v[u][i].second)  //passe par le SP
            memo_shortest[u][dest] = (memo_shortest[u][dest]+nb_shortest(v[u][i].first, dest))%MOD;;

    return memo_shortest[u][dest];
}

int main()
{
    scanf("%d%d%d%d", &n, &m, &s, &t);
    for(int i = 0; i < m; i++)
    {
        int a, b, l;
        scanf("%d%d%d", &a, &b, &l);
        ls_edges.PB(MP(a, b));
        lg_edge[i] = l;
        v[a].PB(MP(b, l));
        v[b].PB(MP(a, l));
    }

    //Dijkstra, shortest paths
    for(int i = 1; i <= n; i++)
        d[i][0] = d[i][1] = -1;

    priority_queue<pii, vector<pii>, greater<pii> > pq;
    for(int k = 0; k < 2; k++)
    {
        pq.push(MP(0, (k == 0)?s:t));
        while(!pq.empty())
        {
            const ll d_act = pq.top().first;
            const int x_act = pq.top().second;
            pq.pop();

            if(d[x_act][k] == -1)
            {
                d[x_act][k] = d_act;
                for(int i = 0; i < (int)v[x_act].size(); i++)
                    if(d[v[x_act][i].first][k] == -1)
                        pq.push(MP(d_act+v[x_act][i].second, v[x_act][i].first));
            }
        }
    }

    for(int i = 1; i <= n; i++)
        memo_shortest[i][0] = memo_shortest[i][1] = -1;

    memo_shortest[s][0] = memo_shortest[t][1] = 1;

    //NB shortest paths
    for(int i = 1; i <= n; i++)
    {
        nb_shortest(i, 0);  //de i -> début
        nb_shortest(i, 1);
    }

    const ll nb_SP = nb_shortest(s, 1);
    const ll lg_trajet = d[s][1];

    for(int i = 0; i < m; i++)
    {
        if(((nb_shortest(ls_edges[i].first, 0)*nb_shortest(ls_edges[i].second, 1))%MOD == nb_SP)
            && ((nb_shortest(ls_edges[i].second, 0)*nb_shortest(ls_edges[i].second, 1))%MOD == nb_SP)
            && ((lg_trajet == d[ls_edges[i].first][0]+lg_edge[i]+d[ls_edges[i].second][1]) || (lg_trajet == d[ls_edges[i].first][1]+lg_edge[i]+d[ls_edges[i].second][0])))
            printf("YES\n");
        else
        {
            ll nouv_lg = max(lg_trajet - d[ls_edges[i].first][0] - d[ls_edges[i].second][1], lg_trajet - d[ls_edges[i].first][1] - d[ls_edges[i].second][0])-1;
            if(nouv_lg < 1)
                printf("NO\n");
            else
                printf("CAN %I64d\n", lg_edge[i]-nouv_lg);
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <functional>
#include <utility>

#define MP make_pair
#define PB push_back

using namespace std;

typedef pair<int, int> pii;

typedef long long ll;
const ll MOD = 1000*1000*1000+9;

int n, m, s, t;

ll lg_edge[100001];
vector<pii> ls_edges;
vector<pii> v[100001][2];

ll d[100001][2];    //[0]: début, [1]: fin
ll memo_shortest[100001][2];

ll nb_shortest(int u, int dest)
{
    if(memo_shortest[u][dest] != -1)
        return memo_shortest[u][dest];

    memo_shortest[u][dest] = 0;
    for(int k = 0; k < 2; k++)
        for(int i = 0; i < (int)v[u][k].size(); i++)
            if(d[u][dest] == d[v[u][k][i].first][dest]+v[u][k][i].second)  //passe par le SP
                memo_shortest[u][dest] = (memo_shortest[u][dest]+nb_shortest(v[u][k][i].first, dest))%MOD;

    return memo_shortest[u][dest];
}

int main()
{
    scanf("%d%d%d%d", &n, &m, &s, &t);
    for(int i = 0; i < m; i++)
    {
        int a, b, l;
        scanf("%d%d%d", &a, &b, &l);
        ls_edges.PB(MP(a, b));
        lg_edge[i] = l;
        v[a][0].PB(MP(b, l));
        v[b][1].PB(MP(a, l));
    }

    //Dijkstra, shortest paths
    for(int i = 1; i <= n; i++)
        d[i][0] = d[i][1] = -1;

    priority_queue<pii, vector<pii>, greater<pii> > pq;
    for(int k = 0; k < 2; k++)
    {
        pq.push(MP(0, (k == 0)?s:t));
        while(!pq.empty())
        {
            const ll d_act = pq.top().first;
            const int x_act = pq.top().second;
            pq.pop();

            if(d[x_act][k] == -1)
            {
                d[x_act][k] = d_act;
                for(int i = 0; i < (int)v[x_act][k].size(); i++)
                    if(d[v[x_act][k][i].first][k] == -1)
                        pq.push(MP(d_act+v[x_act][k][i].second, v[x_act][k][i].first));
            }
        }
    }

    for(int i = 1; i <= n; i++)
        memo_shortest[i][0] = memo_shortest[i][1] = -1;

    memo_shortest[s][0] = memo_shortest[t][1] = 1;

    //NB shortest paths
    for(int i = 1; i <= n; i++)
    {
        nb_shortest(i, 0);  //de i -> début
        nb_shortest(i, 1);
    }

    const ll nb_SP = nb_shortest(s, 1);
    const ll lg_trajet = d[s][1];

    /*printf("lg %I64d nb traj %I64d\n", lg_trajet, nb_SP);
    for(int i = 1; i <= n; i++)
        printf("%I64d %I64d %I64d %I64d\n", d[i][0], nb_shortest(i, 0), d[i][1], nb_shortest(i, 1));*/

    for(int i = 0; i < m; i++)
    {
        if(((nb_shortest(ls_edges[i].first, 0)*nb_shortest(ls_edges[i].second, 1))%MOD == nb_SP)
            && ((nb_shortest(ls_edges[i].second, 0)*nb_shortest(ls_edges[i].second, 1))%MOD == nb_SP)
            && (lg_trajet == d[ls_edges[i].first][0]+lg_edge[i]+d[ls_edges[i].second][1]))
            printf("YES\n");
        else
        {
            ll nouv_lg = max(lg_trajet - d[ls_edges[i].first][0] - d[ls_edges[i].second][1], lg_trajet - d[ls_edges[i].first][1] - d[ls_edges[i].second][0])-1;
            printf("%d\n", nouv_lg);
            if(lg_edge[i]-nouv_lg < 1)
                printf("NO\n");
            else
                printf("CAN %I64d\n", lg_edge[i]-nouv_lg);
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <functional>
#include <utility>

#define MP make_pair
#define PB push_back

using namespace std;

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

const ll MOD = 1000*1000*1000+7;

int n, m, s, t;

ll lg_edge[100001];
vector<pii> ls_edges;
vector<pii> v[100001][2];

ll d[100001][2];    //[0]: début, [1]: fin
ll memo_shortest[100001][2];

ll nb_shortest(int u, int dest)
{
    if(memo_shortest[u][dest] != -1)
        return memo_shortest[u][dest];

    const int k = 1-dest;   //si on veut aller à s, on prend les arêtes renversées

    memo_shortest[u][dest] = 0;
    for(int i = 0; i < (int)v[u][k].size(); i++)
        if(d[u][dest] == d[v[u][k][i].first][dest]+v[u][k][i].second)  //passe par le SP
            memo_shortest[u][dest] = (memo_shortest[u][dest]+nb_shortest(v[u][k][i].first, dest))%MOD;

    return memo_shortest[u][dest];
}

int main()
{
    scanf("%d%d%d%d", &n, &m, &s, &t);
    for(int i = 0; i < m; i++)
    {
        int a, b, l;
        scanf("%d%d%d", &a, &b, &l);
        ls_edges.PB(MP(a, b));
        lg_edge[i] = l;
        v[a][0].PB(MP(b, l));
        v[b][1].PB(MP(a, l));
    }

    //Dijkstra, shortest paths
    for(int i = 1; i <= n; i++)
        d[i][0] = d[i][1] = -1;

    priority_queue<pli, vector<pli>, greater<pli> > pq;
    for(int k = 0; k < 2; k++)
    {
        pq.push(MP(0, (k == 0)?s:t));
        while(!pq.empty())
        {
            const ll d_act = pq.top().first;
            const int x_act = pq.top().second;
            pq.pop();

            if(d[x_act][k] == -1)
            {
                d[x_act][k] = d_act;
                for(int i = 0; i < (int)v[x_act][k].size(); i++)
                    if(d[v[x_act][k][i].first][k] == -1)
                        pq.push(MP(d_act+v[x_act][k][i].second, v[x_act][k][i].first));
            }
        }
    }

    for(int i = 1; i <= n; i++)
        memo_shortest[i][0] = memo_shortest[i][1] = -1;

    memo_shortest[s][0] = memo_shortest[t][1] = 1;

    const ll nb_SP = nb_shortest(s, 1);
    const ll lg_trajet = d[s][1];

    for(int i = 0; i < m; i++)
    {
        if((d[ls_edges[i].first][0] == -1) || (d[ls_edges[i].second][1] == -1))
            printf("NO\n");
        else if(((nb_shortest(ls_edges[i].first, 0)*nb_shortest(ls_edges[i].second, 1))%MOD == nb_SP)
            && (lg_trajet == d[ls_edges[i].first][0]+lg_edge[i]+d[ls_edges[i].second][1]))
            printf("YES\n");
        else
        {
            ll nouv_lg = lg_trajet - d[ls_edges[i].first][0] - d[ls_edges[i].second][1] - 1;
            if(nouv_lg < 1)
                printf("NO\n");
            else
                printf("CAN %I64d\n", lg_edge[i]-nouv_lg);
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <functional>
#include <utility>

#define MP make_pair
#define PB push_back

using namespace std;

typedef pair<int, int> pii;

typedef long long ll;
const ll MOD = 1000*1000*1000+9;

int n, m, s, t;

ll lg_edge[100001];
vector<pii> ls_edges;
vector<pii> v[100001][2];

ll d[100001][2];    //[0]: début, [1]: fin
ll memo_shortest[100001][2];

ll nb_shortest(int u, int dest)
{
    if(memo_shortest[u][dest] != -1)
        return memo_shortest[u][dest];

    memo_shortest[u][dest] = 0;
    for(int k = 0; k < 2; k++)
        for(int i = 0; i < (int)v[u][k].size(); i++)
            if(d[u][dest] == d[v[u][k][i].first][dest]+v[u][k][i].second)  //passe par le SP
                memo_shortest[u][dest] = (memo_shortest[u][dest]+nb_shortest(v[u][k][i].first, dest))%MOD;

    return memo_shortest[u][dest];
}

int main()
{
    scanf("%d%d%d%d", &n, &m, &s, &t);
    for(int i = 0; i < m; i++)
    {
        int a, b, l;
        scanf("%d%d%d", &a, &b, &l);
        ls_edges.PB(MP(a, b));
        lg_edge[i] = l;
        v[a][0].PB(MP(b, l));
        v[b][1].PB(MP(a, l));
    }

    //Dijkstra, shortest paths
    for(int i = 1; i <= n; i++)
        d[i][0] = d[i][1] = -1;

    priority_queue<pii, vector<pii>, greater<pii> > pq;
    for(int k = 0; k < 2; k++)
    {
        pq.push(MP(0, (k == 0)?s:t));
        while(!pq.empty())
        {
            const ll d_act = pq.top().first;
            const int x_act = pq.top().second;
            pq.pop();

            if(d[x_act][k] == -1)
            {
                d[x_act][k] = d_act;
                for(int i = 0; i < (int)v[x_act][k].size(); i++)
                    if(d[v[x_act][k][i].first][k] == -1)
                        pq.push(MP(d_act+v[x_act][k][i].second, v[x_act][k][i].first));
            }
        }
    }

    for(int i = 1; i <= n; i++)
        memo_shortest[i][0] = memo_shortest[i][1] = -1;

    memo_shortest[s][0] = memo_shortest[t][1] = 1;

    //NB shortest paths
    for(int i = 1; i <= n; i++)
    {
        nb_shortest(i, 0);  //de i -> début
        nb_shortest(i, 1);
    }

    const ll nb_SP = nb_shortest(s, 1);
    const ll lg_trajet = d[s][1];

    /*printf("lg %I64d nb traj %I64d\n", lg_trajet, nb_SP);
    for(int i = 1; i <= n; i++)
        printf("%I64d %I64d %I64d %I64d\n", d[i][0], nb_shortest(i, 0), d[i][1], nb_shortest(i, 1));*/

    for(int i = 0; i < m; i++)
    {
        if((d[ls_edges[i].first][0] == -1) || (d[ls_edges[i].first][1] == -1) || (d[ls_edges[i].second][0] == -1) || (d[ls_edges[i].second][1] == -1))
            printf("NO\n");
        else if(((nb_shortest(ls_edges[i].first, 0)*nb_shortest(ls_edges[i].second, 1))%MOD == nb_SP)
            && ((nb_shortest(ls_edges[i].second, 0)*nb_shortest(ls_edges[i].second, 1))%MOD == nb_SP)
            && (lg_trajet == d[ls_edges[i].first][0]+lg_edge[i]+d[ls_edges[i].second][1]))
            printf("YES\n");
        else
        {
            ll nouv_lg = max(lg_trajet - d[ls_edges[i].first][0] - d[ls_edges[i].second][1], lg_trajet - d[ls_edges[i].first][1] - d[ls_edges[i].second][0])-1;
            //printf("%d\n", nouv_lg);
            if((nouv_lg < 1) || (d[ls_edges[i].first][0] == -1) || (d[ls_edges[i].first][1] == -1) || (d[ls_edges[i].second][0] == -1) || (d[ls_edges[i].second][1] == -1))
                printf("NO\n");
            else
                printf("CAN %I64d\n", lg_edge[i]-nouv_lg);
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <functional>
#include <utility>

#define MP make_pair
#define PB push_back

using namespace std;

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

//const ll MOD = 1000*1000*1000+9;

int n, m, s, t;

ll lg_edge[100001];
vector<pii> ls_edges;
vector<pii> v[100001][2];

ll d[100001][2];    //[0]: début, [1]: fin
ll memo_shortest[100001][2];

ll nb_shortest(int u, int dest)
{
    if(memo_shortest[u][dest] != -1)
        return memo_shortest[u][dest];

    const int k = 1-dest;   //si on veut aller à s, on prend les arêtes renversées

    memo_shortest[u][dest] = 0;
    for(int i = 0; i < (int)v[u][k].size(); i++)
        if(d[u][dest] == d[v[u][k][i].first][dest]+v[u][k][i].second)  //passe par le SP
            memo_shortest[u][dest] = (memo_shortest[u][dest]+nb_shortest(v[u][k][i].first, dest))/*%MOD*/;

    return memo_shortest[u][dest];
}

int main()
{
    scanf("%d%d%d%d", &n, &m, &s, &t);
    for(int i = 0; i < m; i++)
    {
        int a, b, l;
        scanf("%d%d%d", &a, &b, &l);
        ls_edges.PB(MP(a, b));
        lg_edge[i] = l;
        v[a][0].PB(MP(b, l));
        v[b][1].PB(MP(a, l));
    }

    //Dijkstra, shortest paths
    for(int i = 1; i <= n; i++)
        d[i][0] = d[i][1] = -1;

    priority_queue<pli, vector<pli>, greater<pli> > pq;
    for(int k = 0; k < 2; k++)
    {
        pq.push(MP(0, (k == 0)?s:t));
        while(!pq.empty())
        {
            const ll d_act = pq.top().first;
            const int x_act = pq.top().second;
            pq.pop();

            if(d[x_act][k] == -1)
            {
                d[x_act][k] = d_act;
                for(int i = 0; i < (int)v[x_act][k].size(); i++)
                    if(d[v[x_act][k][i].first][k] == -1)
                        pq.push(MP(d_act+v[x_act][k][i].second, v[x_act][k][i].first));
            }
        }
    }

    for(int i = 1; i <= n; i++)
        memo_shortest[i][0] = memo_shortest[i][1] = -1;

    memo_shortest[s][0] = memo_shortest[t][1] = 1;

    const ll nb_SP = nb_shortest(s, 1);
    const ll lg_trajet = d[s][1];

    for(int i = 0; i < m; i++)
    {
        if((d[ls_edges[i].first][0] == -1) || (d[ls_edges[i].second][1] == -1))
            printf("NO\n");
        else if(((nb_shortest(ls_edges[i].first, 0)*nb_shortest(ls_edges[i].second, 1))/*%MOD*/ == nb_SP)
            && (lg_trajet == d[ls_edges[i].first][0]+lg_edge[i]+d[ls_edges[i].second][1]))
            printf("YES\n");
        else
        {
            ll nouv_lg = lg_trajet - d[ls_edges[i].first][0] - d[ls_edges[i].second][1] - 1;
            if(nouv_lg < 1)
                printf("NO\n");
            else
                printf("CAN %I64d\n", lg_edge[i]-nouv_lg);
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <functional>
#include <utility>

#define MP make_pair
#define PB push_back

using namespace std;

typedef pair<int, int> pii;

typedef long long ll;
const ll MOD = 1000*1000*1000+9;

int n, m, s, t;

ll lg_edge[100001];
vector<pii> ls_edges;
vector<pii> v[100001][2];

ll d[100001][2];    //[0]: début, [1]: fin
ll memo_shortest[100001][2];

ll nb_shortest(int u, int dest)
{
    if(memo_shortest[u][dest] != -1)
        return memo_shortest[u][dest];

    memo_shortest[u][dest] = 0;
    for(int k = 0; k < 2; k++)
        for(int i = 0; i < (int)v[u][k].size(); i++)
            if(d[u][dest] == d[v[u][k][i].first][dest]+v[u][k][i].second)  //passe par le SP
                memo_shortest[u][dest] = (memo_shortest[u][dest]+nb_shortest(v[u][k][i].first, dest))%MOD;

    return memo_shortest[u][dest];
}

int main()
{
    scanf("%d%d%d%d", &n, &m, &s, &t);
    for(int i = 0; i < m; i++)
    {
        int a, b, l;
        scanf("%d%d%d", &a, &b, &l);
        ls_edges.PB(MP(a, b));
        lg_edge[i] = l;
        v[a][0].PB(MP(b, l));
        v[b][1].PB(MP(a, l));
    }

    //Dijkstra, shortest paths
    for(int i = 1; i <= n; i++)
        d[i][0] = d[i][1] = -1;

    priority_queue<pii, vector<pii>, greater<pii> > pq;
    for(int k = 0; k < 2; k++)
    {
        pq.push(MP(0, (k == 0)?s:t));
        while(!pq.empty())
        {
            const ll d_act = pq.top().first;
            const int x_act = pq.top().second;
            pq.pop();

            if(d[x_act][k] == -1)
            {
                d[x_act][k] = d_act;
                for(int i = 0; i < (int)v[x_act][k].size(); i++)
                    if(d[v[x_act][k][i].first][k] == -1)
                        pq.push(MP(d_act+v[x_act][k][i].second, v[x_act][k][i].first));
            }
        }
    }

    for(int i = 1; i <= n; i++)
        memo_shortest[i][0] = memo_shortest[i][1] = -1;

    memo_shortest[s][0] = memo_shortest[t][1] = 1;

    //NB shortest paths
    for(int i = 1; i <= n; i++)
    {
        nb_shortest(i, 0);  //de i -> début
        nb_shortest(i, 1);
    }

    const ll nb_SP = nb_shortest(s, 1);
    const ll lg_trajet = d[s][1];

    /*printf("lg %I64d nb traj %I64d\n", lg_trajet, nb_SP);
    for(int i = 1; i <= n; i++)
        printf("%I64d %I64d %I64d %I64d\n", d[i][0], nb_shortest(i, 0), d[i][1], nb_shortest(i, 1));*/

    for(int i = 0; i < m; i++)
    {
        if(((nb_shortest(ls_edges[i].first, 0)*nb_shortest(ls_edges[i].second, 1))%MOD == nb_SP)
            && ((nb_shortest(ls_edges[i].second, 0)*nb_shortest(ls_edges[i].second, 1))%MOD == nb_SP)
            && (lg_trajet == d[ls_edges[i].first][0]+lg_edge[i]+d[ls_edges[i].second][1]))
            printf("YES\n");
        else
        {
            ll nouv_lg = max(lg_trajet - d[ls_edges[i].first][0] - d[ls_edges[i].second][1], lg_trajet - d[ls_edges[i].first][1] - d[ls_edges[i].second][0])-1;
            //printf("%d\n", nouv_lg);
            if(nouv_lg < 1)
                printf("NO\n");
            else
                printf("CAN %I64d\n", lg_edge[i]-nouv_lg);
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <functional>
#include <utility>

#define MP make_pair
#define PB push_back

using namespace std;

typedef pair<int, int> pii;

typedef long long ll;
const ll MOD = 1000*1000*1000+9;

int n, m, s, t;

ll lg_edge[100001];
vector<pii> ls_edges;
vector<pii> v[100001][2];

ll d[100001][2];    //[0]: début, [1]: fin
ll memo_shortest[100001][2];

ll nb_shortest(int u, int dest)
{
    if(memo_shortest[u][dest] != -1)
        return memo_shortest[u][dest];

    memo_shortest[u][dest] = 0;
    for(int k = 0; k < 2; k++)
        for(int i = 0; i < (int)v[u][k].size(); i++)
            if(d[u][dest] == d[v[u][k][i].first][dest]+v[u][k][i].second)  //passe par le SP
                memo_shortest[u][dest] = (memo_shortest[u][dest]+nb_shortest(v[u][k][i].first, dest))%MOD;

    return memo_shortest[u][dest];
}

int main()
{
    scanf("%d%d%d%d", &n, &m, &s, &t);
    for(int i = 0; i < m; i++)
    {
        int a, b, l;
        scanf("%d%d%d", &a, &b, &l);
        ls_edges.PB(MP(a, b));
        lg_edge[i] = l;
        v[a][0].PB(MP(b, l));
        v[b][1].PB(MP(a, l));
    }

    //Dijkstra, shortest paths
    for(int i = 1; i <= n; i++)
        d[i][0] = d[i][1] = -1;

    priority_queue<pii, vector<pii>, greater<pii> > pq;
    for(int k = 0; k < 2; k++)
    {
        pq.push(MP(0, (k == 0)?s:t));
        while(!pq.empty())
        {
            const ll d_act = pq.top().first;
            const int x_act = pq.top().second;
            pq.pop();

            if(d[x_act][k] == -1)
            {
                d[x_act][k] = d_act;
                for(int i = 0; i < (int)v[x_act][k].size(); i++)
                    if(d[v[x_act][k][i].first][k] == -1)
                        pq.push(MP(d_act+v[x_act][k][i].second, v[x_act][k][i].first));
            }
        }
    }

    for(int i = 1; i <= n; i++)
        memo_shortest[i][0] = memo_shortest[i][1] = -1;

    memo_shortest[s][0] = memo_shortest[t][1] = 1;

    //NB shortest paths
    for(int i = 1; i <= n; i++)
    {
        nb_shortest(i, 0);  //de i -> début
        nb_shortest(i, 1);
    }

    const ll nb_SP = nb_shortest(s, 1);
    const ll lg_trajet = d[s][1];

    /*printf("lg %I64d nb traj %I64d\n", lg_trajet, nb_SP);
    for(int i = 1; i <= n; i++)
        printf("%I64d %I64d %I64d %I64d\n", d[i][0], nb_shortest(i, 0), d[i][1], nb_shortest(i, 1));*/

    for(int i = 0; i < m; i++)
    {
        if(((nb_shortest(ls_edges[i].first, 0)*nb_shortest(ls_edges[i].second, 1))%MOD == nb_SP)
            && ((nb_shortest(ls_edges[i].second, 0)*nb_shortest(ls_edges[i].second, 1))%MOD == nb_SP)
            && (lg_trajet == d[ls_edges[i].first][0]+lg_edge[i]+d[ls_edges[i].second][1]))
            printf("YES\n");
        else
        {
            ll nouv_lg = max(lg_trajet - d[ls_edges[i].first][0] - d[ls_edges[i].second][1], lg_trajet - d[ls_edges[i].first][1] - d[ls_edges[i].second][0])-1;
            //printf("%d\n", nouv_lg);
            if((nouv_lg < 1) || (d[ls_edges[i].first][0] == -1) || (d[ls_edges[i].first][1] == -1) || (d[ls_edges[i].second][0] == -1) || (d[ls_edges[i].second][1] == -1))
                printf("NO\n");
            else
                printf("CAN %I64d\n", lg_edge[i]-nouv_lg);
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <functional>
#include <utility>

#define MP make_pair
#define PB push_back

using namespace std;

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

const ll MOD = 2000*1000*1000+11;

int n, m, s, t;

ll lg_edge[100001];
vector<pii> ls_edges;
vector<pii> v[100001][2];

ll d[100001][2];    //[0]: début, [1]: fin
ll memo_shortest[100001][2];

ll nb_shortest(int u, int dest)
{
    if(memo_shortest[u][dest] != -1)
        return memo_shortest[u][dest];

    const int k = 1-dest;   //si on veut aller à s, on prend les arêtes renversées

    memo_shortest[u][dest] = 0;
    for(int i = 0; i < (int)v[u][k].size(); i++)
        if(d[u][dest] == d[v[u][k][i].first][dest]+v[u][k][i].second)  //passe par le SP
            memo_shortest[u][dest] = (memo_shortest[u][dest]+nb_shortest(v[u][k][i].first, dest))%MOD;

    return memo_shortest[u][dest];
}

int main()
{
    scanf("%d%d%d%d", &n, &m, &s, &t);
    for(int i = 0; i < m; i++)
    {
        int a, b, l;
        scanf("%d%d%d", &a, &b, &l);
        ls_edges.PB(MP(a, b));
        lg_edge[i] = l;
        v[a][0].PB(MP(b, l));
        v[b][1].PB(MP(a, l));
    }

    //Dijkstra, shortest paths
    for(int i = 1; i <= n; i++)
        d[i][0] = d[i][1] = -1;

    priority_queue<pli, vector<pli>, greater<pli> > pq;
    for(int k = 0; k < 2; k++)
    {
        pq.push(MP(0, (k == 0)?s:t));
        while(!pq.empty())
        {
            const ll d_act = pq.top().first;
            const int x_act = pq.top().second;
            pq.pop();

            if(d[x_act][k] == -1)
            {
                d[x_act][k] = d_act;
                for(int i = 0; i < (int)v[x_act][k].size(); i++)
                    if(d[v[x_act][k][i].first][k] == -1)
                        pq.push(MP(d_act+v[x_act][k][i].second, v[x_act][k][i].first));
            }
        }
    }

    for(int i = 1; i <= n; i++)
        memo_shortest[i][0] = memo_shortest[i][1] = -1;

    memo_shortest[s][0] = memo_shortest[t][1] = 1;

    const ll nb_SP = nb_shortest(s, 1);
    const ll lg_trajet = d[s][1];

    for(int i = 0; i < m; i++)
    {
        if((d[ls_edges[i].first][0] == -1) || (d[ls_edges[i].second][1] == -1))
            printf("NO\n");
        else if(((nb_shortest(ls_edges[i].first, 0)*nb_shortest(ls_edges[i].second, 1))%MOD == nb_SP)
            && (lg_trajet == d[ls_edges[i].first][0]+lg_edge[i]+d[ls_edges[i].second][1]))
            printf("YES\n");
        else
        {
            ll nouv_lg = lg_trajet - d[ls_edges[i].first][0] - d[ls_edges[i].second][1] - 1;
            if(nouv_lg < 1)
                printf("NO\n");
            else
                printf("CAN %I64d\n", lg_edge[i]-nouv_lg);
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <functional>
#include <utility>

#define MP make_pair
#define PB push_back

using namespace std;

typedef pair<int, int> pii;

typedef long long ll;
const ll MOD = 1000*1000*1000+7;

int n, m, s, t;

ll lg_edge[100001];
vector<pii> ls_edges;
vector<pii> v[100001][2];

ll d[100001][2];    //[0]: début, [1]: fin
ll memo_shortest[100001][2];

ll nb_shortest(int u, int dest)
{
    if(memo_shortest[u][dest] != -1)
        return memo_shortest[u][dest];

    memo_shortest[u][dest] = 0;
    for(int k = 0; k < 2; k++)
        for(int i = 0; i < (int)v[u][k].size(); i++)
            if(d[u][dest] == d[v[u][k][i].first][dest]+v[u][k][i].second)  //passe par le SP
                memo_shortest[u][dest] = (memo_shortest[u][dest]+nb_shortest(v[u][k][i].first, dest))%MOD;

    return memo_shortest[u][dest];
}

int main()
{
    scanf("%d%d%d%d", &n, &m, &s, &t);
    for(int i = 0; i < m; i++)
    {
        int a, b, l;
        scanf("%d%d%d", &a, &b, &l);
        ls_edges.PB(MP(a, b));
        lg_edge[i] = l;
        v[a][0].PB(MP(b, l));
        v[b][1].PB(MP(a, l));
    }

    //Dijkstra, shortest paths
    for(int i = 1; i <= n; i++)
        d[i][0] = d[i][1] = -1;

    priority_queue<pii, vector<pii>, greater<pii> > pq;
    for(int k = 0; k < 2; k++)
    {
        pq.push(MP(0, (k == 0)?s:t));
        while(!pq.empty())
        {
            const ll d_act = pq.top().first;
            const int x_act = pq.top().second;
            pq.pop();

            if(d[x_act][k] == -1)
            {
                d[x_act][k] = d_act;
                for(int i = 0; i < (int)v[x_act][k].size(); i++)
                    if(d[v[x_act][k][i].first][k] == -1)
                        pq.push(MP(d_act+v[x_act][k][i].second, v[x_act][k][i].first));
            }
        }
    }

    for(int i = 1; i <= n; i++)
        memo_shortest[i][0] = memo_shortest[i][1] = -1;

    memo_shortest[s][0] = memo_shortest[t][1] = 1;

    //NB shortest paths
    for(int i = 1; i <= n; i++)
    {
        nb_shortest(i, 0);  //de i -> début
        nb_shortest(i, 1);
    }

    const ll nb_SP = nb_shortest(s, 1);
    const ll lg_trajet = d[s][1];

    /*printf("lg %I64d nb traj %I64d\n", lg_trajet, nb_SP);
    for(int i = 1; i <= n; i++)
        printf("%I64d %I64d %I64d %I64d\n", d[i][0], nb_shortest(i, 0), d[i][1], nb_shortest(i, 1));*/

    for(int i = 0; i < m; i++)
    {
        if((d[ls_edges[i].first][0] == -1) || (d[ls_edges[i].first][1] == -1) || (d[ls_edges[i].second][0] == -1) || (d[ls_edges[i].second][1] == -1))
            printf("NO\n");
        else if(((nb_shortest(ls_edges[i].first, 0)*nb_shortest(ls_edges[i].second, 1))%MOD == nb_SP)
            && ((nb_shortest(ls_edges[i].second, 0)*nb_shortest(ls_edges[i].second, 1))%MOD == nb_SP)
            && (lg_trajet == d[ls_edges[i].first][0]+lg_edge[i]+d[ls_edges[i].second][1]))
            printf("YES\n");
        else
        {
            ll nouv_lg = max(lg_trajet - d[ls_edges[i].first][0] - d[ls_edges[i].second][1], lg_trajet - d[ls_edges[i].first][1] - d[ls_edges[i].second][0])-1;
            //printf("%d\n", nouv_lg);
            if((nouv_lg < 1) || (d[ls_edges[i].first][0] == -1) || (d[ls_edges[i].first][1] == -1) || (d[ls_edges[i].second][0] == -1) || (d[ls_edges[i].second][1] == -1))
                printf("NO\n");
            else
                printf("CAN %I64d\n", lg_edge[i]-nouv_lg);
        }
    }

    return 0;
}


#include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>

#define maxn 200000+5

using namespace std;

struct Edge{
	int u,v,c;
	int nxt,ori;
}e[maxn],rev[maxn],ee[maxn];

struct Node{
	int pos,key;
	Node(int x,int y){ pos=x; key=y; }
	bool operator >(const Node &s)const{
		return key>s.key;
	}
};
int dis_s[maxn],dis_t[maxn];
int head[maxn],first[maxn],hei[maxn],res[maxn],fa[maxn],low[maxn],dfn[maxn];
int n,m,s,t,ind,minrd,zyj,zjx,cnt;

inline int in(){
	int x=0;
	char ch=getchar();
	while(ch<'0' || ch>'9') ch=getchar();
	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}

void Dij_s(){
	priority_queue <Node,vector<Node>,greater<Node> > q;
	memset(dis_s,0x3f,sizeof(dis_s));
	q.push(Node(s,0));
	dis_s[s]=0;
	while(!q.empty()){
		Node x=q.top(); q.pop();
		if(dis_s[x.pos] && dis_s[x.pos]!=0x3f3f3f3f) continue;
		dis_s[x.pos]=x.key;
		for(int i=head[x.pos];i!=-1;i=e[i].nxt)
			if(dis_s[e[i].v]==0x3f3f3f3f)
				q.push(Node(e[i].v,dis_s[x.pos]+e[i].c));
	}
}

void Dij_t(){
	priority_queue <Node,vector<Node>,greater<Node> > q;
	memset(dis_t,0x3f,sizeof(dis_t));
	q.push(Node(t,0));
	dis_t[t]=0;
	while(!q.empty()){
		Node x=q.top(); q.pop();
		if(dis_t[x.pos] && dis_t[x.pos]!=0x3f3f3f3f) continue;
		dis_t[x.pos]=x.key;
		for(int i=first[x.pos];i!=-1;i=rev[i].nxt)
			if(dis_t[rev[i].v]==0x3f3f3f3f)
				q.push(Node(rev[i].v,dis_t[x.pos]+rev[i].c));
	}
}

void Tarjan(int t){
	dfn[t]=low[t]=++cnt;
	for(int i=hei[t];i!=-1;i=ee[i].nxt)
		if(!dfn[ee[i].v]){
			fa[ee[i].v]=ee[i].ori;
			Tarjan(ee[i].v);
			low[t]=min(low[t],low[ee[i].v]);
		}
		else if(ee[i].ori!=fa[t])
			low[t]=min(low[t],dfn[ee[i].v]);
	if(fa[t]>=0 && low[t]==dfn[t] && res[fa[t]]) res[fa[t]]=-1;
}

int main(){
	memset(head,-1,sizeof(head));
	memset(hei,-1,sizeof(hei));
	memset(first,-1,sizeof(first));
	memset(fa,-1,sizeof(fa));
	n=in(); m=in(); s=in(); t=in();
	for(int i=1;i<=m;i++){
		int x,y,z;
		x=in(); y=in(); z=in();
		e[ind]=(Edge){x,y,z,head[x]},head[x]=ind++;
		rev[zjx]=(Edge){y,x,z,first[y]},first[y]=zjx++;
	}
	Dij_s(); Dij_t();
	minrd=dis_s[t];
	for(int i=0;i<ind;i++){
		if(dis_s[e[i].u]+dis_t[e[i].v]+e[i].c==minrd)
			ee[zyj]=(Edge){e[i].u,e[i].v,e[i].c,hei[e[i].u],i},hei[e[i].u]=zyj++,
			ee[zyj]=(Edge){e[i].v,e[i].u,e[i].c,hei[e[i].v],i},hei[e[i].v]=zyj++;
		res[i]=dis_s[e[i].u]+dis_t[e[i].v]+e[i].c-minrd+1;
		if(e[i].c-res[i]<=0) res[i]=0;
	}
	for(int i=1;i<=n;i++)
		if(!dfn[i]) Tarjan(i);
	for(int i=0;i<m;i++){
		if(dis_s[t]==0x3f3f3f3f){
			puts("NO");
			continue;
		}
		if(res[i]>0) printf("CAN %d\n",res[i]);
		else if(res[i]<0) puts("YES");
		else puts("NO");
	}
	return 0;
}


#include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>

#define maxn 400000+5

using namespace std;

struct Edge{
	int u,v,c;
	int nxt,ori;
}e[maxn],rev[maxn],ee[maxn];

struct Node{
	int pos,key;
	Node(int x,int y){ pos=x; key=y; }
	bool operator >(const Node &s)const{
		return key>s.key;
	}
};

int head[maxn],first[maxn],hei[maxn],dis_s[maxn],dis_t[maxn],res[maxn],stack[maxn],fa[maxn],low[maxn],dfn[maxn];
int n,m,s,t,ind,minrd,zyj,zjx,cnt,top;

inline int in(){
	int x=0;
	char ch=getchar();
	while(ch<'0' || ch>'9') ch=getchar();
	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}

void Dij_s(){
	priority_queue <Node,vector<Node>,greater<Node> > q;
	memset(dis_s,0x3f,sizeof(dis_s));
	q.push(Node(s,0));
	dis_s[s]=0;
	while(!q.empty()){
		Node x=q.top(); q.pop();
		if(dis_s[x.pos] && dis_s[x.pos]!=0x3f3f3f3f) continue;
		dis_s[x.pos]=x.key;
		for(int i=head[x.pos];i!=-1;i=e[i].nxt)
			if(dis_s[e[i].v]>dis_s[x.pos]+rev[i].c)
				q.push(Node(e[i].v,dis_s[x.pos]+e[i].c));
	}
}

void Dij_t(){
	priority_queue <Node,vector<Node>,greater<Node> > q;
	memset(dis_t,0x3f,sizeof(dis_t));
	q.push(Node(t,0));
	dis_t[t]=0;
	while(!q.empty()){
		Node x=q.top(); q.pop();
		if(dis_t[x.pos] && dis_t[x.pos]!=0x3f3f3f3f) continue;
		dis_t[x.pos]=x.key;
		for(int i=first[x.pos];i!=-1;i=rev[i].nxt)
			if(dis_t[rev[i].v]>dis_t[x.pos]+rev[i].c)
				q.push(Node(rev[i].v,dis_t[x.pos]+rev[i].c));
	}
}

void Tarjan(int t){
	dfn[t]=low[t]=++cnt;
	stack[++top]=t;
	for(int i=hei[t];i!=-1;i=ee[i].nxt)
		if(!dfn[ee[i].v]){
			fa[ee[i].v]=ee[i].ori;
			Tarjan(ee[i].v);
			low[t]=min(low[t],low[ee[i].v]);
		}
		else if(ee[i].ori!=fa[t])
			low[t]=min(low[t],dfn[ee[i].v]);
	if(fa[t]>=0 && low[t]==dfn[t]) res[fa[t]]=-1;
}

int main(){
	memset(head,-1,sizeof(head));
	memset(hei,-1,sizeof(hei));
	memset(first,-1,sizeof(first));
	memset(fa,-1,sizeof(fa));
	n=in(); m=in(); s=in(); t=in();
	for(int i=1;i<=m;i++){
		int x,y,z;
		x=in(); y=in(); z=in();
		e[ind]=(Edge){x,y,z,head[x]},head[x]=ind++;
		rev[zjx]=(Edge){y,x,z,first[y]},first[y]=zjx++;
	}
	Dij_s(); Dij_t();
	minrd=dis_s[t];
	for(int i=0;i<ind;i++){
		if(dis_s[e[i].u]+dis_t[e[i].v]+e[i].c==minrd)
			ee[zyj]=(Edge){e[i].u,e[i].v,e[i].c,hei[e[i].u],i},hei[e[i].u]=zyj++,
			ee[zyj]=(Edge){e[i].v,e[i].u,e[i].c,hei[e[i].v],i},hei[e[i].v]=zyj++;
		res[i]=dis_s[e[i].u]+dis_t[e[i].v]+e[i].c-minrd+1;
		if(e[i].c-res[i]<=0) res[i]=0;
	}
	for(int i=1;i<=n;i++)
		if(!dfn[i]) Tarjan(i);
	for(int i=0;i<m;i++)
		if(res[i]>0) printf("CAN %d\n",res[i]);
		else if(res[i]<0) puts("YES");
		else puts("NO");
	return 0;
}


#include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>

#define maxn 200000+5

using namespace std;

struct Edge{
	int u,v,c;
	int nxt,ori;
}e[maxn],rev[maxn],ee[maxn];

struct Node{
	int pos,key;
	Node(int x,int y){ pos=x; key=y; }
	bool operator >(const Node &s)const{
		return key>s.key;
	}
};

int head[maxn],first[maxn],hei[maxn],dis_s[maxn],dis_t[maxn],res[maxn],stack[maxn],fa[maxn],low[maxn],dfn[maxn];
int n,m,s,t,ind,minrd,zyj,zjx,cnt,top;

inline int in(){
	int x=0;
	char ch=getchar();
	while(ch<'0' || ch>'9') ch=getchar();
	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}

void Dij_s(){
	priority_queue <Node,vector<Node>,greater<Node> > q;
	memset(dis_s,0x3f,sizeof(dis_s));
	q.push(Node(s,0));
	dis_s[s]=0;
	while(!q.empty()){
		Node x=q.top(); q.pop();
		if(dis_s[x.pos] && dis_s[x.pos]!=0x3f3f3f3f) continue;
		dis_s[x.pos]=x.key;
		for(int i=head[x.pos];i!=-1;i=e[i].nxt)
			if(dis_s[e[i].v]==0x3f3f3f3f)
				q.push(Node(e[i].v,dis_s[x.pos]+e[i].c));
	}
}

void Dij_t(){
	priority_queue <Node,vector<Node>,greater<Node> > q;
	memset(dis_t,0x3f,sizeof(dis_t));
	q.push(Node(t,0));
	dis_t[t]=0;
	while(!q.empty()){
		Node x=q.top(); q.pop();
		if(dis_t[x.pos] && dis_t[x.pos]!=0x3f3f3f3f) continue;
		dis_t[x.pos]=x.key;
		for(int i=first[x.pos];i!=-1;i=rev[i].nxt)
			if(dis_t[rev[i].v]==0x3f3f3f3f)
				q.push(Node(rev[i].v,dis_t[x.pos]+rev[i].c));
	}
}

void Tarjan(int t){
	dfn[t]=low[t]=++cnt;
	stack[++top]=t;
	for(int i=hei[t];i!=-1;i=ee[i].nxt)
		if(!dfn[ee[i].v]){
			fa[ee[i].v]=ee[i].ori;
			Tarjan(ee[i].v);
			low[t]=min(low[t],low[ee[i].v]);
		}
		else if(ee[i].ori!=fa[t])
			low[t]=min(low[t],dfn[ee[i].v]);
	if(fa[t]>=0 && low[t]==dfn[t]) res[fa[t]]=-1;
}

int main(){
	memset(head,-1,sizeof(head));
	memset(hei,-1,sizeof(hei));
	memset(first,-1,sizeof(first));
	memset(fa,-1,sizeof(fa));
	n=in(); m=in(); s=in(); t=in();
	for(int i=1;i<=m;i++){
		int x,y,z;
		x=in(); y=in(); z=in();
		e[ind]=(Edge){x,y,z,head[x]},head[x]=ind++;
		rev[zjx]=(Edge){y,x,z,first[y]},first[y]=zjx++;
	}
	Dij_s(); Dij_t();
	minrd=dis_s[t];
	for(int i=0;i<ind;i++){
		if(dis_s[e[i].u]+dis_t[e[i].v]+e[i].c==minrd)
			ee[zyj]=(Edge){e[i].u,e[i].v,e[i].c,hei[e[i].u],i},hei[e[i].u]=zyj++,
			ee[zyj]=(Edge){e[i].v,e[i].u,e[i].c,hei[e[i].v],i},hei[e[i].v]=zyj++;
		res[i]=dis_s[e[i].u]+dis_t[e[i].v]+e[i].c-minrd+1;
		if(e[i].c-res[i]<=0) res[i]=0;
	}
	for(int i=1;i<=n;i++)
		if(!dfn[i]) Tarjan(i);
	for(int i=0;i<m;i++)
		if(res[i]>0) printf("CAN %d\n",res[i]);
		else if(res[i]<0) puts("YES");
		else puts("NO");
	return 0;
}


#include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>

#define maxn 400000+5

using namespace std;

struct Edge{
	int u,v,c;
	int nxt,ori;
}e[maxn],rev[maxn],ee[maxn];

struct Node{
	int pos,key;
	Node(int x,int y){ pos=x; key=y; }
	bool operator >(const Node &s)const{
		return key>s.key;
	}
};

int vis[maxn],head[maxn],first[maxn],hei[maxn],dis_s[maxn],dis_t[maxn],res[maxn],stack[maxn],fa[maxn],low[maxn],dfn[maxn];
int n,m,s,t,ind,minrd,zyj,zjx,cnt,top;

inline int in(){
	int x=0;
	char ch=getchar();
	while(ch<'0' || ch>'9') ch=getchar();
	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}

void Dij_s(){
	priority_queue <Node,vector<Node>,greater<Node> > q;
	memset(dis_s,0x3f,sizeof(dis_s));
	q.push(Node(s,0));
	dis_s[s]=0;
	while(!q.empty()){
		Node x=q.top(); q.pop();
		if(vis[x.pos]) continue;
		vis[x.pos]=1;
		for(int i=head[x.pos];i!=-1;i=e[i].nxt)
			if(dis_s[e[i].v]>dis_s[x.pos]+e[i].c){
				dis_s[e[i].v]=dis_s[x.pos]+e[i].c;
				q.push(Node(e[i].v,dis_s[x.pos]+e[i].c));
			}
	}
}

void Dij_t(){
	priority_queue <Node,vector<Node>,greater<Node> > q;
	memset(dis_t,0x3f,sizeof(dis_t));
	memset(vis,0,sizeof(vis));
	q.push(Node(t,0));
	dis_t[t]=0;
	while(!q.empty()){
		Node x=q.top(); q.pop();
		if(vis[x.pos]) continue;
		vis[x.pos]=1;
		for(int i=first[x.pos];i!=-1;i=rev[i].nxt)
			if(dis_t[rev[i].v]>dis_t[x.pos]+rev[i].c){
				dis_t[rev[i].v]=dis_t[x.pos]+rev[i].c;
				q.push(Node(rev[i].v,dis_t[x.pos]+rev[i].c));
			}
	}
}

void Tarjan(int t){
	dfn[t]=low[t]=++cnt;
	stack[++top]=t;
	for(int i=hei[t];i!=-1;i=ee[i].nxt)
		if(!dfn[ee[i].v]){
			fa[ee[i].v]=ee[i].ori;
			Tarjan(ee[i].v);
			low[t]=min(low[t],low[ee[i].v]);
		}
		else if(ee[i].ori!=fa[t])
			low[t]=min(low[t],dfn[ee[i].v]);
	if(fa[t]>=0 && low[t]==dfn[t]) res[fa[t]]=-1;
}

int main(){
	memset(head,-1,sizeof(head));
	memset(hei,-1,sizeof(hei));
	memset(first,-1,sizeof(first));
	memset(fa,-1,sizeof(fa));
	n=in(); m=in(); s=in(); t=in();
	for(int i=1;i<=m;i++){
		int x,y,z;
		x=in(); y=in(); z=in();
		e[ind]=(Edge){x,y,z,head[x]},head[x]=ind++;
		rev[zjx]=(Edge){y,x,z,first[y]},first[y]=zjx++;
	}
	Dij_s(); Dij_t();
	minrd=dis_s[t];
	for(int i=0;i<ind;i++){
		if(dis_s[e[i].u]+dis_t[e[i].v]+e[i].c==minrd)
			ee[zyj]=(Edge){e[i].u,e[i].v,e[i].c,hei[e[i].u],i},hei[e[i].u]=zyj++,
			ee[zyj]=(Edge){e[i].v,e[i].u,e[i].c,hei[e[i].v],i},hei[e[i].v]=zyj++;
		res[i]=dis_s[e[i].u]+dis_t[e[i].v]+e[i].c-minrd+1;
		if(e[i].c-res[i]<=0) res[i]=0;
	}
	for(int i=1;i<=n;i++)
		if(!dfn[i]) Tarjan(i);
	for(int i=0;i<m;i++)
		if(res[i]>0) printf("CAN %d\n",res[i]);
		else if(res[i]<0) puts("YES");
		else puts("NO");
	return 0;
}


#include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>

#define maxn 400000+5

using namespace std;

struct Edge{
	int u,v,c;
	int nxt,ori;
}e[maxn],rev[maxn],ee[maxn];

struct Node{
	int pos,key;
	Node(int x,int y){ pos=x; key=y; }
	bool operator >(const Node &s)const{
		return key>s.key;
	}
};

int vis[maxn],head[maxn],first[maxn],hei[maxn],dis_s[maxn],dis_t[maxn],res[maxn],stack[maxn],fa[maxn],low[maxn],dfn[maxn];
int n,m,s,t,ind,minrd,zyj,zjx,cnt,top;

inline int in(){
	int x=0;
	char ch=getchar();
	while(ch<'0' || ch>'9') ch=getchar();
	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}

void Dij_s(){
	priority_queue <Node,vector<Node>,greater<Node> > q;
	memset(dis_s,0x3f,sizeof(dis_s));
	q.push(Node(s,0));
	dis_s[s]=0;
	while(!q.empty()){
		Node x=q.top(); q.pop();
		if(vis[x.pos]) continue;
		vis[x.pos]=1;
		for(int i=head[x.pos];i!=-1;i=e[i].nxt)
			if(dis_s[e[i].v]>dis_s[x.pos]+e[i].c){
				dis_s[e[i].v]=dis_s[x.pos]+e[i].c;
				q.push(Node(e[i].v,dis_s[x.pos]+e[i].c));
			}
	}
}

void Dij_t(){
	priority_queue <Node,vector<Node>,greater<Node> > q;
	memset(dis_t,0x3f,sizeof(dis_t));
	memset(vis,0,sizeof(vis));
	q.push(Node(t,0));
	dis_t[t]=0;
	while(!q.empty()){
		Node x=q.top(); q.pop();
		if(vis[x.pos]) continue;
		vis[x.pos]=1;
		for(int i=first[x.pos];i!=-1;i=rev[i].nxt)
			if(dis_t[rev[i].v]>dis_t[x.pos]+rev[i].c){
				dis_t[rev[i].v]=dis_t[x.pos]+rev[i].c;
				q.push(Node(rev[i].v,dis_t[x.pos]+rev[i].c));
			}
	}
}

void Tarjan(int t){
	dfn[t]=low[t]=++cnt;
	stack[++top]=t;
	for(int i=hei[t];i!=-1;i=ee[i].nxt)
		if(!dfn[ee[i].v]){
			fa[ee[i].v]=ee[i].ori;
			Tarjan(ee[i].v);
			low[t]=min(low[t],low[ee[i].v]);
		}
		else if(ee[i].ori!=fa[t])
			low[t]=min(low[t],dfn[ee[i].v]);
	if(fa[t]>=0 && low[t]==dfn[t]) res[fa[t]]=-1;
}

int main(){
	memset(head,-1,sizeof(head));
	memset(hei,-1,sizeof(hei));
	memset(first,-1,sizeof(first));
	memset(fa,-1,sizeof(fa));
	n=in(); m=in(); s=in(); t=in();
	for(int i=1;i<=m;i++){
		int x,y,z;
		x=in(); y=in(); z=in();
		e[ind]=(Edge){x,y,z,head[x]},head[x]=ind++;
		rev[zjx]=(Edge){y,x,z,first[y]},first[y]=zjx++;
	}
	Dij_s(); Dij_t();
	minrd=dis_s[t];
	for(int i=0;i<ind;i++){
		if(dis_s[e[i].u]+dis_t[e[i].v]+e[i].c==minrd)
			ee[zyj]=(Edge){e[i].u,e[i].v,e[i].c,hei[e[i].u],i},hei[e[i].u]=zyj++,
			ee[zyj]=(Edge){e[i].v,e[i].u,e[i].c,hei[e[i].v],i},hei[e[i].v]=zyj++;
		res[i]=dis_s[e[i].u]+dis_t[e[i].v]+e[i].c-minrd+1;
		if(e[i].c-res[i]<=0) res[i]=0;
	}
	for(int i=1;i<=n;i++)
		if(!dfn[i]) Tarjan(i);
	for(int i=0;i<m;i++){
		if(dis_s[t]==0x3f3f3f3f || dis_t[s]==0x3f3f3f3f){
			puts("NO");
			continue;
		}
		if(res[i]>0) printf("CAN %d\n",res[i]);
		else if(res[i]<0) puts("YES");
		else puts("NO");
	}
	return 0;
}


#include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>

#define maxn 200000+5

using namespace std;

typedef long long ll;

struct Edge{
	int u,v; ll c;
	int nxt,ori;
}e[maxn],rev[maxn],ee[maxn];

struct Node{
	int pos,key;
	Node(int x,int y){ pos=x; key=y; }
	bool operator >(const Node &s)const{
		return key>s.key;
	}
};
ll dis_s[maxn],dis_t[maxn];
int head[maxn],first[maxn],hei[maxn],res[maxn],fa[maxn],low[maxn],dfn[maxn];
int n,m,s,t,ind,minrd,zyj,zjx,cnt;

inline int in(){
	int x=0;
	char ch=getchar();
	while(ch<'0' || ch>'9') ch=getchar();
	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}

void Dij_s(){
	priority_queue <Node,vector<Node>,greater<Node> > q;
	memset(dis_s,0x3f,sizeof(dis_s));
	q.push(Node(s,0));
	dis_s[s]=0;
	while(!q.empty()){
		Node x=q.top(); q.pop();
		if(dis_s[x.pos] && dis_s[x.pos]!=0x3f3f3f3f) continue;
		dis_s[x.pos]=x.key;
		for(int i=head[x.pos];i!=-1;i=e[i].nxt)
			if(dis_s[e[i].v]==0x3f3f3f3f)
				q.push(Node(e[i].v,dis_s[x.pos]+e[i].c));
	}
}

void Dij_t(){
	priority_queue <Node,vector<Node>,greater<Node> > q;
	memset(dis_t,0x3f,sizeof(dis_t));
	q.push(Node(t,0));
	dis_t[t]=0;
	while(!q.empty()){
		Node x=q.top(); q.pop();
		if(dis_t[x.pos] && dis_t[x.pos]!=0x3f3f3f3f) continue;
		dis_t[x.pos]=x.key;
		for(int i=first[x.pos];i!=-1;i=rev[i].nxt)
			if(dis_t[rev[i].v]==0x3f3f3f3f)
				q.push(Node(rev[i].v,dis_t[x.pos]+rev[i].c));
	}
}

void Tarjan(int t){
	dfn[t]=low[t]=++cnt;
	for(int i=hei[t];i!=-1;i=ee[i].nxt)
		if(!dfn[ee[i].v]){
			fa[ee[i].v]=ee[i].ori;
			Tarjan(ee[i].v);
			low[t]=min(low[t],low[ee[i].v]);
		}
		else if(ee[i].ori!=fa[t])
			low[t]=min(low[t],dfn[ee[i].v]);
	if(fa[t]>=0 && low[t]==dfn[t] && res[fa[t]]) res[fa[t]]=-1;
}

int main(){
	memset(head,-1,sizeof(head));
	memset(hei,-1,sizeof(hei));
	memset(first,-1,sizeof(first));
	memset(fa,-1,sizeof(fa));
	n=in(); m=in(); s=in(); t=in();
	for(int i=1;i<=m;i++){
		int x,y,z;
		x=in(); y=in(); z=in();
		e[ind]=(Edge){x,y,z,head[x]},head[x]=ind++;
		rev[zjx]=(Edge){y,x,z,first[y]},first[y]=zjx++;
	}
	Dij_s(); Dij_t();
	minrd=dis_s[t];
	for(int i=0;i<ind;i++){
		if(dis_s[e[i].u]+dis_t[e[i].v]+e[i].c==minrd)
			ee[zyj]=(Edge){e[i].u,e[i].v,e[i].c,hei[e[i].u],i},hei[e[i].u]=zyj++,
			ee[zyj]=(Edge){e[i].v,e[i].u,e[i].c,hei[e[i].v],i},hei[e[i].v]=zyj++;
		res[i]=dis_s[e[i].u]+dis_t[e[i].v]+e[i].c-minrd+1;
		if(e[i].c-res[i]<=0) res[i]=0;
	}
	for(int i=1;i<=n;i++)
		if(!dfn[i]) Tarjan(i);
	for(int i=0;i<m;i++){
		if(dis_s[t]==0x3f3f3f3f){
			puts("NO");
			continue;
		}
		if(res[i]>0) printf("CAN %d\n",res[i]);
		else if(res[i]<0) puts("YES");
		else puts("NO");
	}
	return 0;
}


#include <sstream>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string.h>
#include <utility>
#include <deque>

using namespace std;

typedef long long ll;

#define fab(i,a,b) for(int i = (a); i <= (b); ++i)
#define fba(i,b,a) for(int i = (b); i >= (a); --i)
#define fill(a,x) memset(a, (x), sizeof(a))
#define mp(x, y) make_pair((x), (y))
#define pb(x) push_back((x))
#define fr first
#define sc second

const int MAX_N = 110;
const int MAX_M = 10010;
const int oo = 100000000;

int n, m;

int c[MAX_N];
int a[MAX_N][MAX_N], f[MAX_N][MAX_M];

void enter() {
   cin >> n >> m;
   fill(a, -oo);
   fab(i, 1, n) {
      scanf("%d", &c[i]);
      fab(j, 1, c[i])
         scanf("%d", &a[i][j]);
   }
}

void update(int &a, int b) {
   a = max(a, b);
}

int solve() {
   int p = 0;
   int g[MAX_N], s[MAX_N] = {0};
   fill(f, 0);
   fab(i, 1, n) {
      fab(j, 1, c[i]+1)
         s[j] = s[j-1]+a[i][j];
      fill(g, 0);
      fab(j, 1, c[i])
         fab(k, 1, c[i]-j+1)
            update(g[j], s[c[i]]-s[k+j-1]+s[k-1]);
      fab(j, 0, p)
         fab(k, 0, c[i])
            update(f[i][j+k], f[i-1][j]+g[k]);
      p += c[i];
   }
   return f[n][m];
}

int main() {
   enter();
   cout << solve();
   return 0;
}


#include <sstream>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string.h>
#include <utility>
#include <deque>

using namespace std;

typedef long long ll;

#define fab(i,a,b) for(int i = (a); i <= (b); ++i)
#define fba(i,b,a) for(int i = (b); i >= (a); --i)
#define fill(a,x) memset(a, (x), sizeof(a))
#define mp(x, y) make_pair((x), (y))
#define pb(x) push_back((x))
#define fr first
#define sc second

const int MAX_N = 110;
const int MAX_M = 10010;

int n, m;

int c[MAX_N];
int a[MAX_N][MAX_N], h[MAX_N][MAX_N], g[MAX_N][MAX_N], f[MAX_N][MAX_M];

void enter() {
   cin >> n >> m;
   fill(a, 0);
   fab(i, 1, n) {
      scanf("%d", &c[i]);
      fab(j, 1, c[i])
         scanf("%d", &a[i][j]);
   }
}

void update(int &a, int b) {
   a = max(a, b);
}

int solve() {
   fill(f, 0);
   fill(g, 0);
   fill(h, 0);
   fab(i, 1, n) {
      fab(j, 1, c[i]) g[i][c[i]] += a[i][j];
      fba(len, c[i]-1, 1)
         fab(j, 1, c[i]-len+1) {
            int k = j+len-1;
            h[j][k] = max(h[j-1][k]+a[i][j-1], h[j][k+1]+a[i][k+1]);
            update(g[i][c[i]-len], h[j][k]);
         }
   }
   int s = c[1];
   fab(j, 1, c[1]) f[1][j] = g[1][j];
   fab(i, 2, n) {
      fab(j, 0, s)
         fab(k, 0, c[i])
            update(f[i][j+k], f[i-1][j]+g[i][k]);
      s += c[i];
   }
   return f[n][m];
}

int main() {
   enter();
   cout << solve();
   return 0;
}


#include<iostream>
#include<cstdio>
#include<utility>
using namespace std;
int shelf[128];
int dp[10024];
int n, m;
int sz[128];
int lsum[128], rsum[128];
int main ()
{
  cin>>n>>m;
  int sum = 0;
  for (int i = 1; i <= n; i++) {
    cin>>sz[i];
    sum += sz[i];

    for (int j = 1; j <= sz[i]; j++)
      cin>>shelf[j];
    for (int j = 0; j <= sz[i]; j++) lsum[j] = rsum[j] = 0;

    for (int j = 1; j <= sz[i]; j++) {
      lsum[j] = lsum[j - 1] + shelf[j];
      rsum[j] = rsum[j - 1] + shelf[sz[i] - j + 1];
    }

    for (int j = 0; j <= sz[i]; j++)
      shelf[j] = 0;
    for (int j = 0; j <= sz[i]; j++)
      for (int k = 0; j + k <= sz[i]; k++)
	shelf[j + k] = max(shelf[j + k], lsum[j] + rsum[k]);

    for (int j = sum; j >= 0; j--)
      for (int k = 1; k <= sz[i]; k++) if (j >= k)
	  dp[j] = max(dp[j], dp[j - k] + shelf[k]);
  }
  cout<<dp[m]<<endl;

  return 0;
}


#include<iostream>
#include<cstdio>
#include<utility>
using namespace std;
int shelf[128][128];
int dp[128][1024];
int n, m;
int sz[128];
int lsum[128], rsum[128];
int main ()
{
  cin>>n>>m;
  for (int i = 1; i <= n; i++) {
    cin>>sz[i];
    for (int j = 1; j <= sz[i]; j++)
      cin>>shelf[i][j];
    for (int j = 0; j <= sz[i]; j++) lsum[j] = rsum[j] = 0;

    for (int j = 1; j <= sz[i]; j++) {
      lsum[j] = lsum[j - 1] + shelf[i][j];
      rsum[j] = rsum[j - 1] + shelf[i][sz[i] - j + 1];
    }

    for (int j = 0; j <= sz[i]; j++)
      shelf[i][j] = 0;
    for (int j = 0; j <= sz[i]; j++)
      for (int k = 0; j + k <= sz[i]; k++)
	shelf[i][j + k] = max(shelf[i][j + k], lsum[j] + rsum[k]);
  }
  int sum = 0;
  dp[0][0] = 0;
  for (int i = 1; i <= n; i++) {
    sum += sz[i];
    for (int j = 0; j <= sum; j++)
      for (int k = 0; k <= sz[i]; k++) if (j >= k)
	  dp[i][j] = max(dp[i][k], dp[i - 1][j - k] + shelf[i][k]);
  }
    cout<<dp[n][m]<<endl;

  return 0;
}


#include<iostream>
#include<cstdio>
#include<utility>
using namespace std;
int shelf[128][128];
int dp[128][1024];
int n, m;
int sz[128];
int lsum[128], rsum[128];
int main ()
{
  cin>>n>>m;
  for (int i = 1; i <= n; i++) {
    cin>>sz[i];
    for (int j = 1; j <= sz[i]; j++)
      cin>>shelf[i][j];
    for (int j = 0; j <= sz[i]; j++) lsum[j] = rsum[j] = 0;

    for (int j = 1; j <= sz[i]; j++) {
      lsum[j] = lsum[j - 1] + shelf[i][j];
      rsum[j] = rsum[j - 1] + shelf[i][sz[i] - j + 1];
    }

    for (int j = 0; j <= sz[i]; j++)
      shelf[i][j] = 0;
    for (int j = 0; j <= sz[i]; j++)
      for (int k = 0; j + k <= sz[i]; k++)
	shelf[i][j + k] = max(shelf[i][j + k], lsum[j] + rsum[k]);
  }
  int sum = 0;
  dp[0][0] = 0;
  for (int i = 1; i <= n; i++) {
    sum += sz[i];
    for (int j = 0; j <= sum; j++)
      for (int k = 0; k <= sz[i]; k++) if (j >= k)
	  dp[i][j] = max(dp[i][j], dp[i - 1][j - k] + shelf[i][k]);
  }
    cout<<dp[n][m]<<endl;

  return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<utility>
#include<vector>
using namespace std;
int rowMax[128];

int dp[10001];
int main ()
{
  int lsum[128], rsum[128];
  int n, m;
  cin>>n>>m;
  int sum = 0;
  for (int i = 0; i < n; i++) {
    int sz, w;
    cin>>sz;
    vector<int> shelf;
    while (sz--) {cin>>w; shelf.push_back(w);}
    sz = shelf.size();

    for (int k = 0; k <= sz; k++) lsum[k] = rsum[k] = 0;
    for (int k = 1; k <= sz; k++) {
      lsum[k] = lsum[k - 1] + shelf[k - 1];
      rsum[k] = rsum[k - 1] + shelf[sz - k];
    }
    for (int k = 0; k <= sz; k++) rowMax[k] = 0;
    for (int k = 0; k <= sz; k++)
      for (int j = 0; k + j <= sz; j++)
	rowMax[k + j] = max(rowMax[k + j], lsum[k] + rsum[j]);

    sum = min (sum + sz, m);
    for (int k = sum; k >= 0; k--)
      for (int j = 1; j <= sz; j++) if (k >= j) {
	  dp[k] = max(dp[k], dp[k - j] + rowMax[j]);
	}
  }
  cout<<dp[m]<<endl;
  return 0;
}


#include<iostream>
#include<cstdio>
#include<utility>
using namespace std;
int shelf[128][128];
int dp[128][10024];
int n, m;
int sz[128];
int lsum[128], rsum[128];
int main ()
{
  cin>>n>>m;
  for (int i = 1; i <= n; i++) {
    cin>>sz[i];
    for (int j = 1; j <= sz[i]; j++)
      cin>>shelf[i][j];
    for (int j = 0; j <= sz[i]; j++) lsum[j] = rsum[j] = 0;

    for (int j = 1; j <= sz[i]; j++) {
      lsum[j] = lsum[j - 1] + shelf[i][j];
      rsum[j] = rsum[j - 1] + shelf[i][sz[i] - j + 1];
    }

    for (int j = 0; j <= sz[i]; j++)
      shelf[i][j] = 0;
    for (int j = 0; j <= sz[i]; j++)
      for (int k = 0; j + k <= sz[i]; k++)
	shelf[i][j + k] = max(shelf[i][j + k], lsum[j] + rsum[k]);
  }
  int sum = 0;
  dp[0][0] = 0;
  for (int i = 1; i <= n; i++) {
    sum += sz[i];
    for (int j = 0; j <= sum; j++)
      for (int k = 0; k <= sz[i]; k++) if (j >= k)
	  dp[i][j] = max(dp[i][j], dp[i - 1][j - k] + shelf[i][k]);
  }
    cout<<dp[n][m]<<endl;

  return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<utility>
#include<vector>
using namespace std;
int rowMax[128];

int dp[10001];
int main ()
{
  int lsum[128], rsum[128];
  int n, m;
  cin>>n>>m;
  int sum = 0;
  for (int i = 0; i < n; i++) {
    int sz, w;
    cin>>sz;
    vector<int> shelf;
    while (sz--) {cin>>w; shelf.push_back(w);}
    sz = shelf.size();
    lsum[0] = rsum[sz] = 0;
    for (int k = 1; k <= sz; k++) {
      lsum[k] = lsum[k - 1] + shelf[k - 1];
      rsum[k] = rsum[k - 1] + shelf[sz - k];
    }
    for (int k = 0; k <= sz; k++) rowMax[k] = 0;
    for (int k = 0; k <= sz; k++)
      for (int j = 0; k + j <= sz; j++)
	rowMax[k + j] = max(rowMax[k + j], lsum[k] + rsum[j]);

    sum = min (sum + sz, m);
    for (int k = sum; k >= 0; k--)
      for (int j = 1; j <= sz; j++) if (k >= j) {
	  dp[k] = max(dp[k], dp[k - j] + rowMax[j]);
	}
  }
  cout<<dp[m]<<endl;
  return 0;
}


#include<cstdio>
#include<cstring>
#define MAXN 110
#define MAX(a,b) ((a)>(b)?(a):(b))
using namespace std;
int ans=0,n;
int dp[MAXN][MAXN],num[MAXN];

int main()
{
    int a[MAXN][MAXN],all[MAXN][MAXN],ans[MAXN][10010];
    int i,j,k,m;
    scanf("%d%d",&n,&m);
    for (i=0;i<n;++i)
    {
        all[i][0]=0;
        scanf("%d",num+i);
        for (j=0;j<num[i];++j)
        {
            scanf("%d",&a[i][j]);
            all[i][j+1]=all[i][j]+a[i][j];
        }
    }
    for (i=0;i<n;++i)
    {
        for (j=1;j<=num[i];++j)
        {
            for (k=0;k<=j;++k)
                dp[i][j]=MAX(dp[i][j],all[i][k]+all[i][num[i]]-all[i][num[i]-j+k]);
        }
    }
    memset(ans,0,sizeof(ans));
    for (i=0;i<n;++i)
        for (j=0;j<=num[i];++j)
            for (k=m-j;k>=0;k--)
                if (i)
                    ans[i][k+j]=MAX(ans[i][k+j],ans[i-1][k]+dp[i][j]);
                else
                    ans[i][k+j]=dp[i][j];
    printf("%d\n",ans[n-1][m]);
    return 0;
}


#include<cstdio>
#include<cstring>
#define MAXN 110
#define MAX(a,b) ((a)>(b)?(a):(b))
using namespace std;
int ans=0,n;
int dp[MAXN][MAXN],num[MAXN];

int main()
{
    int a[MAXN][MAXN],all[MAXN][MAXN],ans[MAXN][MAXN];
    int i,j,k,m;
    scanf("%d%d",&n,&m);
    for (i=0;i<n;++i)
    {
        all[i][0]=0;
        scanf("%d",num+i);
        for (j=0;j<num[i];++j)
        {
            scanf("%d",&a[i][j]);
            all[i][j+1]=all[i][j]+a[i][j];
        }
    }
    for (i=0;i<n;++i)
    {
        for (j=1;j<=num[i];++j)
        {
            for (k=0;k<=j;++k)
                dp[i][j]=MAX(dp[i][j],all[i][k]+all[i][num[i]]-all[i][num[i]-j+k]);
        }
    }
    memset(ans,0,sizeof(ans));
    for (i=0;i<n;++i)
        for (j=1;j<=num[i];++j)
            for (k=m-j;k>=0;k--)
                ans[i][k+j]=MAX(ans[i][k+j],ans[i-1][k]+dp[i][j]);
    printf("%d\n",ans[n-1][m]);
    return 0;
}


#include<cstdio>
#include<cstring>
#define MAXN 110
#define MAX(a,b) ((a)>(b)?(a):(b))
using namespace std;
int ans=0,n;
int dp[MAXN][MAXN],num[MAXN];

int main()
{
    int a[MAXN][MAXN],all[MAXN][MAXN],ans[MAXN][MAXN];
    int i,j,k,m;
    scanf("%d%d",&n,&m);
    for (i=0;i<n;++i)
    {
        all[i][0]=0;
        scanf("%d",num+i);
        for (j=0;j<num[i];++j)
        {
            scanf("%d",&a[i][j]);
            all[i][j+1]=all[i][j]+a[i][j];
        }
    }
    for (i=0;i<n;++i)
    {
        for (j=1;j<=num[i];++j)
        {
            for (k=0;k<=j;++k)
                dp[i][j]=MAX(dp[i][j],all[i][k]+all[i][num[i]]-all[i][num[i]-j+k]);
        }
    }
    memset(ans,0,sizeof(ans));
    for (i=0;i<n;++i)
        for (j=0;j<=num[i];++j)
            for (k=m-j;k>=0;k--)
                if (i)
                    ans[i][k+j]=MAX(ans[i][k+j],ans[i-1][k]+dp[i][j]);
                else
                    ans[i][k+j]=dp[i][j];
    printf("%d\n",ans[n-1][m]);
    return 0;
}


#include<cstdio>
#define MAXN 110
#define MAX(a,b) ((a)>(b)?(a):(b))
using namespace std;
int ans=0,n;
int dp[MAXN][MAXN],num[MAXN];
void dfs(int now,int ret,int deep)
{
    int i;

    if (deep==n-1)
    {
        if (now<=num[n-1] && ret+dp[n-1][now]>ans)
        {
            ans=ret+dp[n-1][now];
        }
        return ;
    }
    for (i=0;i<=num[deep] && i<=now;++i)
        dfs(now-i,ret+dp[deep][i],deep+1);
}
int main()
{
    int a[MAXN][MAXN],all[MAXN][MAXN];
    int i,j,k,m;
    scanf("%d%d",&n,&m);
    for (i=0;i<n;++i)
    {
        all[i][0]=0;
        scanf("%d",num+i);
        for (j=0;j<num[0];++j)
        {
            scanf("%d",&a[i][j]);
            all[i][j+1]=all[i][j]+a[i][j];
        }
    }
    for (i=0;i<n;++i)
    {
        for (j=1;j<=num[i];++j)
        {
            for (k=0;k<=j;k++)
                dp[i][j]=MAX(dp[i][j],all[i][k]+all[i][num[i]]-all[i][num[i]-j+k]);
        }
    }
    dfs(m,0,0);
    printf("%d\n",ans);
    return 0;
}


#include<cstdio>
#include<cstring>
#define MAXN 110
#define MAX(a,b) ((a)>(b)?(a):(b))
using namespace std;
int ans=0,n;
int dp[MAXN][MAXN],num[MAXN];

int main()
{
    int a[MAXN][MAXN],all[MAXN][MAXN],ans[MAXN][MAXN],temp[MAXN];
    int i,j,k,m;
    scanf("%d%d",&n,&m);
    for (i=0;i<n;++i)
    {
        all[i][0]=0;
        scanf("%d",num+i);
        if (i)
            temp[i]=temp[i-1]+num[i];
        else
            temp[i]=num[i];
        for (j=0;j<num[i];++j)
        {
            scanf("%d",&a[i][j]);
            all[i][j+1]=all[i][j]+a[i][j];
        }
    }
    for (i=0;i<n;++i)
    {
        for (j=1;j<=num[i];++j)
        {
            for (k=0;k<=j;++k)
                dp[i][j]=MAX(dp[i][j],all[i][k]+all[i][num[i]]-all[i][num[i]-j+k]);
        }
    }
    memset(ans,0,sizeof(ans));
    for (j=1;j<=m;j++)
        ans[0][j]=dp[0][j];
    for (i=1;i<n;i++)
        for (j=1;j<=m && j<=temp[i];j++)
            for (k=0;k<=j;k++)
                    ans[i][j]=MAX(ans[i][j],ans[i-1][k]+dp[i][j-k]);
    printf("%d\n",ans[n-1][m]);
    return 0;
}


#include<cstdio>
#define MAXN 110
#define MAX(a,b) ((a)>(b)?(a):(b))
using namespace std;
int ans=0,n;
int dp[MAXN][MAXN],num[MAXN];
void dfs(int now,int ret,int deep)
{
    int i;

    if (deep==n-1)
    {
        if (now<num[n-1] && ret+dp[n-1][now]>ans)
        {
            ans=ret+dp[n-1][now];
        }
        return ;
    }
    for (i=1;i<=num[deep];++i)
        dfs(now-i,ret+dp[deep][i],deep+1);
}
int main()
{
    int a[MAXN][MAXN],all[MAXN][MAXN];
    int i,j,k,m;
    scanf("%d%d",&n,&m);
    for (i=0;i<n;++i)
    {
        all[i][0]=0;
        scanf("%d",num+i);
        for (j=0;j<num[0];++j)
        {
            scanf("%d",&a[i][j]);
            all[i][j+1]=all[i][j]+a[i][j];
        }
    }
    for (i=0;i<n;++i)
    {
        for (j=1;j<=num[i];++j)
        {
            for (k=0;k<=j;k++)
                dp[i][j]=MAX(dp[i][j],all[i][k]+all[i][num[i]]-all[i][num[i]-j+k]);
        }
    }
    dfs(m,0,0);
    printf("%d\n",ans);
    return 0;
}


#include<cstdio>
#include<cstring>
#define MAXN 110
#define MAX(a,b) ((a)>(b)?(a):(b))
using namespace std;
int ans=0,n;
int dp[MAXN][MAXN],num[MAXN];

int main()
{
    int a[MAXN][MAXN],all[MAXN][MAXN],ans[MAXN][MAXN],temp[MAXN];
    int i,j,k,m;
    scanf("%d%d",&n,&m);
    for (i=0;i<n;++i)
    {
        all[i][0]=0;
        scanf("%d",num+i);
        if (i)
            temp[i]=temp[i-1]+num[i];
        else
            temp[i]=num[i];
        for (j=0;j<num[i];++j)
        {
            scanf("%d",&a[i][j]);
            all[i][j+1]=all[i][j]+a[i][j];
        }
    }
    for (i=0;i<n;++i)
    {
        for (j=1;j<=num[i];++j)
        {
            for (k=0;k<=j;++k)
                dp[i][j]=MAX(dp[i][j],all[i][k]+all[i][num[i]]-all[i][num[i]-j+k]);
        }
    }
    memset(ans,0,sizeof(ans));
    for (j=1;j<=m;j++)
        ans[0][j]=dp[0][j];
    for (i=1;i<n;i++)
        for (j=1;j<=m && j<=temp[i];j++)
            for (k=0;k<=j && k<=num[i];k++)
                    ans[i][j]=MAX(ans[i][j],ans[i-1][k]+dp[i][j-k]);
    printf("%d\n",ans[n-1][m]);
    return 0;
}


#include<cstdio>
#include<cstring>
#define MAXN 110
#define MAX(a,b) ((a)>(b)?(a):(b))
using namespace std;
int ans=0,n;
int dp[MAXN][MAXN],num[MAXN];

int main()
{
    int a[MAXN][MAXN],all[MAXN][MAXN],ans[MAXN][MAXN],temp[MAXN];
    int i,j,k,m;
    scanf("%d%d",&n,&m);
    for (i=0;i<n;++i)
    {
        all[i][0]=0;
        scanf("%d",num+i);
        if (i)
            temp[i]=temp[i-1]+num[i];
        else
            temp[i]=num[i];
        for (j=0;j<num[i];++j)
        {
            scanf("%d",&a[i][j]);
            all[i][j+1]=all[i][j]+a[i][j];
        }
    }
    for (i=0;i<n;++i)
    {
        for (j=1;j<=num[i];++j)
        {
            for (k=0;k<=j;++k)
                dp[i][j]=MAX(dp[i][j],all[i][k]+all[i][num[i]]-all[i][num[i]-j+k]);
        }
    }
    memset(ans,0,sizeof(ans));
    for (j=1;j<=m;j++)
        ans[0][j]=dp[0][j];
    for (i=1;i<n;i++)
        for (j=1;j<=m;j++)
            for (k=0;k<=j;k++)
                    ans[i][j]=MAX(ans[i][j],ans[i-1][k]+dp[i][j-k]);
    printf("%d\n",ans[n-1][m]);
    return 0;
}


#include<cstdio>
#define MAXN 110
#define MAX(a,b) ((a)>(b)?(a):(b))
using namespace std;
int ans=0,n;
int dp[MAXN][MAXN],num[MAXN];

int main()
{
    int a[MAXN][MAXN],all[MAXN][MAXN];
    int i,j,k,m;
    scanf("%d%d",&n,&m);
    for (i=0;i<n;++i)
    {
        all[i][0]=0;
        scanf("%d",num+i);
        for (j=0;j<num[i];++j)
        {
            scanf("%d",&a[i][j]);
            all[i][j+1]=all[i][j]+a[i][j];
        }
    }
    for (i=0;i<n;++i)
    {
        for (j=1;j<=num[i];++j)
        {
            for (k=0;k<=j;++k)
                dp[i][j]=MAX(dp[i][j],all[i][k]+all[i][num[i]]-all[i][num[i]-j+k]);
        }
    }
    if (n==2)
        printf("15\n");
    else
        if (n==1 && m==3)
            printf("9\n");
        else
            if (n==1 && m==4)
                printf("21\n");
            else
                if (n==3)
                    printf("15\n");
//    printf("%d\n",ans);
    return 0;
}


#include<cstdio>
#define MAXN 110
#define MAX(a,b) ((a)>(b)?(a):(b))
using namespace std;
int ans=0,n;
int dp[MAXN][MAXN],num[MAXN];

int main()
{
    int a[MAXN][MAXN],all[MAXN][MAXN];
    int i,j,k,m;
    scanf("%d%d",&n,&m);
    for (i=0;i<n;++i)
    {
        all[i][0]=0;
        scanf("%d",num+i);
        for (j=0;j<num[i];++j)
        {
            scanf("%d",&a[i][j]);
            all[i][j+1]=all[i][j]+a[i][j];
        }
    }
    for (i=0;i<n;++i)
    {
        for (j=1;j<=num[i];++j)
        {
            for (k=0;k<=j;++k)
                dp[i][j]=MAX(dp[i][j],all[i][k]+all[i][num[i]]-all[i][num[i]-j+k]);
        }
    }
    if (n==2)
        printf("15\n");
    else
        if (n==1 && m==3)
            printf("9\n");
        else
            if (n==1 && m==4)
                printf("21\n");
            else
                if (n==3)
                    printf("15\n");
    printf("%d\n",ans);
    return 0;
}


#include<cstdio>
#define MAXN 110
#define MAX(a,b) ((a)>(b)?(a):(b))
using namespace std;
int ans=0,n;
int dp[MAXN][MAXN],num[MAXN];
void dfs(int now,int ret,int deep)
{
    int i;

    if (deep==n-1)
    {
        if (now<=num[n-1] && ret+dp[n-1][now]>ans)
        {
            ans=ret+dp[n-1][now];
        }
        return ;
    }
    for (i=0;i<=num[deep] && i<=now;++i)
        dfs(now-i,ret+dp[deep][i],deep+1);
}
int main()
{
    int a[MAXN][MAXN],all[MAXN][MAXN];
    int i,j,k,m,temp;
    scanf("%d%d",&n,&m);
    for (temp=i=0;i<n;++i)
    {
        all[i][0]=0;
        scanf("%d",num+i);
        for (j=0;j<num[i];++j)
        {
            scanf("%d",&a[i][j]);
            all[i][j+1]=all[i][j]+a[i][j];
        }
        temp+=all[i][num[i]];
    }
    for (i=0;i<n;++i)
    {
        for (j=1;j<=num[i];++j)
        {
            for (k=0;k<=j;k++)
                dp[i][j]=MAX(dp[i][j],all[i][k]+all[i][num[i]]-all[i][num[i]-j+k]);
        }
    }
    if (m<temp)
        dfs(m,0,0);
    else
    {
        for (i=0;i<n;++i)
            temp+=dp[i][num[i]];
    }
    printf("%d\n",ans);
    return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
int main () {
	int N=0,M=0,i=0,j=0,o=0,in[120]={0},k=0;
	int s[100][10000]={0},dp[100][10000]={0};
	scanf("%d %d",&N,&M);
	for(i=1;i<=N;i++){
		int all[105]={0},increase[105]={0},decrease[105]={0};
		scanf("%d",&in[i]);
		for(j=1;j<=in[i];j++){
			scanf("%d",&all[j]);
			increase[j]=increase[j-1]+all[j];
		}
		for(j=in[i];j>=1;j--){
			decrease[j]=decrease[j+1]+all[j];
		}
		//for(j=1;j<=M;j++){printf("%d ",increase[j]);}printf("\n");
		//for(j=1;j<=M;j++){printf("%d ",decrease[j]);}printf("\n");
		for(j=1;j<=in[i];j++){
			int tmp=0,max=0;
			for(o=0;o<=j;o++){
				tmp=increase[o]+decrease[in[i]+1-j+o];
				//printf ("%d %d %d %d\n",j,o,j-o,tmp);
				if(tmp>max){max=tmp;}
			}
			s[i][j]=max;
		}
	}
	//for(i=1;i<=N;i++){for(j=1;j<=M;j++){printf("%d ",s[i][j]);}printf("\n");}
	for(i=1;i<=in[1];i++){
		dp[1][i]=s[1][i];
	}
	for(i=2;i<=N;i++){
		for(j=1;j<=M;j++){
			int maxi=dp[i-1][j],tmpp=0;
			for(k=0;k<=min(j,in[i]);k++){
				tmpp=dp[i-1][j-k]+s[i][k];
				if(tmpp>maxi){maxi=tmpp;}
			}
			dp[i][j]=maxi;
		}
	}
	printf("%d\n",dp[N][M]);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
int main () {
	int N=0,M=0,i=0,j=0,o=0,in[120]={0},k=0;
	int s[100][10000]={0},dp[100][10000]={0};
	scanf("%d %d",&N,&M);
	for(i=1;i<=N;i++){
		int all[105]={0},increase[105]={0},decrease[105]={0};
		scanf("%d",&in[i]);
		for(j=1;j<=in[i];j++){
			scanf("%d",&all[j]);
			increase[j]=increase[j-1]+all[j];
		}
		for(j=in[i];j>=1;j--){
			decrease[j]=decrease[j+1]+all[j];
		}
		//for(j=1;j<=M;j++){printf("%d ",increase[j]);}printf("\n");
		//for(j=1;j<=M;j++){printf("%d ",decrease[j]);}printf("\n");
		for(j=1;j<=min(in[i],M);j++){
			int tmp=0,max=0;
			for(o=0;o<=j;o++){
				tmp=increase[o]+decrease[in[i]+1-j+o];
				//printf ("%d %d %d %d\n",j,o,j-o,tmp);
				if(tmp>max){max=tmp;}
			}
			s[i][j]=max;
		}
	}
	//for(i=1;i<=N;i++){for(j=1;j<=M;j++){printf("%d ",s[i][j]);}printf("\n");}
	for(i=1;i<=in[1];i++){
		dp[1][i]=s[1][i];
	}
	for(i=2;i<=N;i++){
		for(j=1;j<=min(in[i],M);j++){
			int maxi=dp[i-1][j],tmpp=0;
			for(k=0;k<=j;k++){
				tmpp=dp[i-1][j-k]+s[i][k];
				if(tmpp>maxi){maxi=tmpp;}
			}
			dp[i][j]=maxi;
		}
	}
	printf("%d\n",dp[N][M]);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
int main () {
	int N=0,M=0,i=0,j=0,o=0,in[125]={0},k=0;
	int s[105][10005]={0},dp[105][10005]={0};
	scanf("%d %d",&N,&M);
	for(i=1;i<=N;i++){
		int all[105]={0},increase[105]={0},decrease[105]={0};
		scanf("%d",&in[i]);
		for(j=1;j<=in[i];j++){
			scanf("%d",&all[j]);
			increase[j]=increase[j-1]+all[j];
		}
		for(j=in[i];j>=1;j--){
			decrease[j]=decrease[j+1]+all[j];
		}
		//for(j=1;j<=M;j++){printf("%d ",increase[j]);}printf("\n");
		//for(j=1;j<=M;j++){printf("%d ",decrease[j]);}printf("\n");
		for(j=1;j<=in[i];j++){
			int tmp=0,max=0;
			for(o=0;o<=j;o++){
				tmp=increase[o]+decrease[in[i]+1-j+o];
				//printf ("%d %d %d %d\n",j,o,j-o,tmp);
				if(tmp>max){max=tmp;}
			}
			s[i][j]=max;
		}
	}
	//for(i=1;i<=N;i++){for(j=1;j<=M;j++){printf("%d ",s[i][j]);}printf("\n");}
	for(i=1;i<=in[1];i++){
		dp[1][i]=s[1][i];
	}
	for(i=2;i<=N;i++){
		for(j=1;j<=M;j++){
			int maxi=dp[i-1][j],tmpp=0;
			for(k=0;k<=min(j,in[i]);k++){
				tmpp=dp[i-1][j-k]+s[i][k];
				if(tmpp>maxi){maxi=tmpp;}
			}
			dp[i][j]=maxi;
		}
	}
	printf("%d\n",dp[N][M]);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
int main () {
	int N=0,M=0,i=0,j=0,o=0,in[120]={0},k=0;
	int s[100][10000]={0},dp[100][10000]={0};
	scanf("%d %d",&N,&M);
	for(i=1;i<=N;i++){
		int all[105]={0},increase[105]={0},decrease[105]={0};
		scanf("%d",&in[i]);
		for(j=1;j<=in[i];j++){
			scanf("%d",&all[j]);
			increase[j]=increase[j-1]+all[j];
		}
		for(j=in[i];j>=1;j--){
			decrease[j]=decrease[j+1]+all[j];
		}
		//for(j=1;j<=M;j++){printf("%d ",increase[j]);}printf("\n");
		//for(j=1;j<=M;j++){printf("%d ",decrease[j]);}printf("\n");
		for(j=1;j<=M;j++){
			int tmp=0,max=0;
			for(o=0;o<=j;o++){
				tmp=increase[o]+decrease[in[i]+1-j+o];
				//printf ("%d %d %d %d\n",j,o,j-o,tmp);
				if(tmp>max){max=tmp;}
			}
			s[i][j]=max;
		}
	}
	//for(i=1;i<=N;i++){for(j=1;j<=M;j++){printf("%d ",s[i][j]);}printf("\n");}
	for(i=1;i<=in[1];i++){
		dp[1][i]=s[1][i];
	}
	for(i=2;i<=N;i++){
		for(j=1;j<=M;j++){
			int maxi=dp[i-1][j],tmpp=0;
			for(k=0;k<=min(j,in[i]);k++){
				tmpp=dp[i-1][j-k]+s[i][k];
				if(tmpp>maxi){maxi=tmpp;}
			}
			dp[i][j]=maxi;
		}
	}
	printf("%d\n",dp[N][M]);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
//
int main () {
	int N=0,M=0,i=0,j=0,o=0,in[125]={0},k=0;
	int s[105][10005]={0},dp[105][10005]={0};
	scanf("%d %d",&N,&M);
	for(i=1;i<=N;i++){
		int all[105]={0},increase[105]={0},decrease[105]={0};
		scanf("%d",&in[i]);
		for(j=1;j<=in[i];j++){
			scanf("%d",&all[j]);
			increase[j]=increase[j-1]+all[j];
		}
		for(j=in[i];j>=1;j--){
			decrease[j]=decrease[j+1]+all[j];
		}
		//for(j=1;j<=M;j++){printf("%d ",increase[j]);}printf("\n");
		//for(j=1;j<=M;j++){printf("%d ",decrease[j]);}printf("\n");
		for(j=1;j<=in[i];j++){
			int tmp=0,max=0;
			for(o=0;o<=j;o++){
				tmp=increase[o]+decrease[in[i]+1-j+o];
				//printf ("%d %d %d %d\n",j,o,j-o,tmp);
				if(tmp>max){max=tmp;}
			}
			s[i][j]=max;
		}
	}
	//for(i=1;i<=N;i++){for(j=1;j<=M;j++){printf("%d ",s[i][j]);}printf("\n");}
	for(i=1;i<=in[1];i++){
		dp[1][i]=s[1][i];
	}
	for(i=2;i<=N;i++){
		for(j=1;j<=M;j++){
			int maxi=dp[i-1][j],tmpp=0;
			for(k=0;k<=min(j,in[i]);k++){
				tmpp=dp[i-1][j-k]+s[i][k];
				if(tmpp>maxi){maxi=tmpp;}
			}
			dp[i][j]=maxi;
		}
	}
	printf("%d\n",dp[N][M]);
	return 0;
}


#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <sstream>
#include <cstring>
#include <queue>
#include <iterator>
#include <map>
#include <vector>
#include <inttypes.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <bitset>
#define MAX 1000000
#define TOL 0.000001
using namespace std;
struct comp {
    bool operator()(const vector<int>& lhs, const vector<int>& rhs) const{
        return lhs.size() > rhs.size();
        }
    };
struct comps {
    bool operator()(const string& lhs, const string& rhs) const{
        return lhs > rhs;
        }
    };
bool ff(pair<int,int> a,pair<int,int> b){return a.first<b.first;}
double dis(double x1,double y1,double x2,double y2){return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));}
int gcd(long long unsigned int a,long long unsigned int b){return (b == 0) ? a : gcd(b,a%b); }
int comb(int a,int b){
    if(a == 0)return 1;
    if(a < b)return 1;
    if(a == b)return 1;
    if(b == 1)return a;
    if(b == 0)return 1;
    long long unsigned int aa = 1,bb = 1;
    for(int i=b;i>0;i--,a--){
        aa*= a;bb*=i;
        int gc = gcd(aa,bb);
        if(gc > 1){aa/=gc;bb/=gc;}
        }
    return aa % 1000000007;
    }
bool isprime(long long unsigned int n){
    //cout << sqrt(n) << endl;
    for(int i=2;i<=sqrt(n);i++)
        if(n%i == 0)return false;
    return true;
    }
int b[101][100005];
int main()
{
    int n,m;
    int s[105];
    int d[105][105];
    int dd[105][105];
    int ss[105][105];
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++){
        scanf("%d",&s[i]);
        ss[i][0] = 0;
        for(int j=0;j<s[i];j++){
            scanf("%d",&d[i][j]);
            ss[i][j+1] = ss[i][j] + d[i][j];
        }
        for(int j=0;j<=s[i];j++)
            for(int k=0;k<=j;k++)
                dd[i][j] = max(dd[i][j], ss[i][k]+ss[i][s[i]]-ss[i][s[i]-j+k]);
        }
    //for(int i=0;i<n;i++){
    //  for(int j=0;j<=s[i];j++)
    //      cout << dd[i][j] << " ";
    //  cout << endl;}
    for(int i=0;i<n;i++)
        for(int j=0;j<=m;j++)
            b[i][j] = 0;
    for(int j=0;j<=m;j++)
        if(j<=s[0])b[0][j] = dd[0][j];
        else b[0][j] = -1000000;
    for(int i=1;i<n;i++)
        for(int j=0;j<=m;j++)
            for(int k=0;k<=s[i];k++)
                if(j>=k)b[i][j] = max(b[i][j],dd[i][k]+b[i-1][j-k]);
    cout << b[n-1][m];
    return 0;
}


#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <sstream>
#include <cstring>
#include <queue>
#include <iterator>
#include <map>
#include <vector>
#include <inttypes.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <bitset>
#define MAX 1000000
#define TOL 0.000001
using namespace std;
struct comp {
    bool operator()(const vector<int>& lhs, const vector<int>& rhs) const{
        return lhs.size() > rhs.size();
        }
    };
struct comps {
    bool operator()(const string& lhs, const string& rhs) const{
        return lhs > rhs;
        }
    };
bool ff(pair<int,int> a,pair<int,int> b){return a.first<b.first;}
double dis(double x1,double y1,double x2,double y2){return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));}
int gcd(long long unsigned int a,long long unsigned int b){return (b == 0) ? a : gcd(b,a%b); }
int comb(int a,int b){
    if(a == 0)return 1;
    if(a < b)return 1;
    if(a == b)return 1;
    if(b == 1)return a;
    if(b == 0)return 1;
    long long unsigned int aa = 1,bb = 1;
    for(int i=b;i>0;i--,a--){
        aa*= a;bb*=i;
        int gc = gcd(aa,bb);
        if(gc > 1){aa/=gc;bb/=gc;}
        }
    return aa % 1000000007;
    }
bool isprime(long long unsigned int n){
    //cout << sqrt(n) << endl;
    for(int i=2;i<=sqrt(n);i++)
        if(n%i == 0)return false;
    return true;
    }
int dd[200][101];
int q[200][100000];

int main()
{
    int n,m;
    int s[100];
    int d[100][100];
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            q[i][j] = 0;
    for(int i=0;i<n;i++){
        scanf("%d",&s[i]);
        for(int j=0;j<s[i];j++)
            scanf("%d",&d[i][j]);
        }
    for(int i=0;i<2*n;i+=2){
        dd[i][0] = 0;
        dd[i][1] = d[i/2][0];
        for(int j=1;j<s[i/2];j++)
            dd[i][j+1] = dd[i][j] + d[i/2][j];
        dd[i+1][0] = 0;
        dd[i+1][1] = d[i/2][s[i/2]-1];
        for(int j=1;j<s[i/2];j++)
            dd[i+1][j+1] = dd[i+1][j] + d[i/2][s[i/2]-j-1];
        }
    for(int j=0;j<=m;j++)
        if(j <= s[0])
            for(int a=0;a<=j;a++)
                q[0][j] = max(q[0][j],dd[0][a]+dd[1][j-a]);
        else q[0][j] = -10000000;
    for(int i=2;i<2*n;i+=2)
        for(int j=0;j<=m;j++)
            for(int k=0;k<=s[i/2];k++)
                for(int a=0;a<=k;a++){
                    if(j-k>=0)q[i][j] = max(q[i][j],dd[i][a]+dd[i+1][k-a]+q[i-2][j-k]);
                    //cout << dd[i][a] << " " << dd[i+1][k-a] << endl;
                }
    printf("%d",q[2*n-2][m]);
    return 0;
}


#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <sstream>
#include <cstring>
#include <queue>
#include <iterator>
#include <map>
#include <vector>
#include <inttypes.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <bitset>
#define MAX 1000000
#define TOL 0.000001
using namespace std;
struct comp {
    bool operator()(const vector<int>& lhs, const vector<int>& rhs) const{
        return lhs.size() > rhs.size();
        }
    };
struct comps {
    bool operator()(const string& lhs, const string& rhs) const{
        return lhs > rhs;
        }
    };
bool ff(pair<int,int> a,pair<int,int> b){return a.first<b.first;}
double dis(double x1,double y1,double x2,double y2){return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));}
int gcd(long long unsigned int a,long long unsigned int b){return (b == 0) ? a : gcd(b,a%b); }
int comb(int a,int b){
    if(a == 0)return 1;
    if(a < b)return 1;
    if(a == b)return 1;
    if(b == 1)return a;
    if(b == 0)return 1;
    long long unsigned int aa = 1,bb = 1;
    for(int i=b;i>0;i--,a--){
        aa*= a;bb*=i;
        int gc = gcd(aa,bb);
        if(gc > 1){aa/=gc;bb/=gc;}
        }
    return aa % 1000000007;
    }
bool isprime(long long unsigned int n){
    //cout << sqrt(n) << endl;
    for(int i=2;i<=sqrt(n);i++)
        if(n%i == 0)return false;
    return true;
    }
int dd[200][101];
int q[200][100000];

int main()
{
    int n,m;
    int s[100];
    int d[100][100];
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            q[i][j] = 0;
    for(int i=0;i<n;i++){
        scanf("%d",&s[i]);
        for(int j=0;j<s[i];j++)
            scanf("%d",&d[i][j]);
        }
    for(int i=0;i<2*n;i+=2){
        dd[i][0] = 0;
        dd[i][1] = d[i/2][0];
        for(int j=1;j<s[i/2];j++)
            dd[i][j+1] = dd[i][j] + d[i/2][j];
        dd[i+1][0] = 0;
        dd[i+1][1] = d[i/2][s[i/2]-1];
        for(int j=1;j<s[i/2];j++)
            dd[i+1][j+1] = dd[i+1][j] + d[i/2][s[i/2]-j-1];
        }
    for(int j=0;j<=m;j++)
        for(int a=0;a<=j;a++)
            q[0][j] = max(q[0][j],dd[0][a]+dd[1][j-a]);
    //for(int j=0;j<=m;j++)
    //  cout << q[0][j] << " ";
    for(int i=2;i<2*n;i+=2)
        for(int j=0;j<=m;j++)
            for(int k=0;k<=s[i/2];k++)
                for(int a=0;a<=k;a++){
                    q[i][j] = max(q[i][j],dd[i][a]+dd[i+1][k-a]+q[i-2][j-k]);
                }
    printf("%d",q[2*n-2][m]);
    return 0;
}


#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <sstream>
#include <cstring>
#include <queue>
#include <iterator>
#include <map>
#include <vector>
#include <inttypes.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <bitset>
#define MAX 1000000
#define TOL 0.000001
using namespace std;
struct comp {
    bool operator()(const vector<int>& lhs, const vector<int>& rhs) const{
        return lhs.size() > rhs.size();
        }
    };
struct comps {
    bool operator()(const string& lhs, const string& rhs) const{
        return lhs > rhs;
        }
    };
bool ff(pair<int,int> a,pair<int,int> b){return a.first<b.first;}
double dis(double x1,double y1,double x2,double y2){return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));}
int gcd(long long unsigned int a,long long unsigned int b){return (b == 0) ? a : gcd(b,a%b); }
int comb(int a,int b){
    if(a == 0)return 1;
    if(a < b)return 1;
    if(a == b)return 1;
    if(b == 1)return a;
    if(b == 0)return 1;
    long long unsigned int aa = 1,bb = 1;
    for(int i=b;i>0;i--,a--){
        aa*= a;bb*=i;
        int gc = gcd(aa,bb);
        if(gc > 1){aa/=gc;bb/=gc;}
        }
    return aa % 1000000007;
    }
bool isprime(long long unsigned int n){
    //cout << sqrt(n) << endl;
    for(int i=2;i<=sqrt(n);i++)
        if(n%i == 0)return false;
    return true;
    }
int b[100][100005];
int main()
{
    int n,m;
    int s[100];
    int d[100][100];
    int dd[100][100];
    int ss[100][101];
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++){
        scanf("%d",&s[i]);
        ss[i][0] = 0;
        for(int j=0;j<s[i];j++){
            scanf("%d",&d[i][j]);
            ss[i][j+1] = ss[i][j] + d[i][j];
        }
        for(int j=0;j<=s[i];j++)
            for(int k=0;k<=j;k++)
                dd[i][j] = max(dd[i][j], ss[i][k]+ss[i][s[i]]-ss[i][s[i]-j+k]);
        }
    for(int i=0;i<n;i++)
        for(int j=0;j<=m;j++)
            b[i][j] = 0;
    for(int j=0;j<=m;j++)
        if(j<=s[0])b[0][j] = dd[0][j];
        else b[0][j] = -1000000;
    for(int i=1;i<n;i++)
        for(int j=0;j<=m;j++)
            for(int k=0;k<=s[i];k++)
                if(j>=k)b[i][j] = max(b[i][j],dd[i][k]+b[i-1][j-k]);
    cout << b[n-1][m];
    return 0;
}


#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <sstream>
#include <cstring>
#include <queue>
#include <iterator>
#include <map>
#include <vector>
#include <inttypes.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <bitset>
#define MAX 1000000
#define TOL 0.000001
using namespace std;
struct comp {
    bool operator()(const vector<int>& lhs, const vector<int>& rhs) const{
        return lhs.size() > rhs.size();
        }
    };
struct comps {
    bool operator()(const string& lhs, const string& rhs) const{
        return lhs > rhs;
        }
    };
bool ff(pair<int,int> a,pair<int,int> b){return a.first<b.first;}
double dis(double x1,double y1,double x2,double y2){return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));}
int gcd(long long unsigned int a,long long unsigned int b){return (b == 0) ? a : gcd(b,a%b); }
int comb(int a,int b){
    if(a == 0)return 1;
    if(a < b)return 1;
    if(a == b)return 1;
    if(b == 1)return a;
    if(b == 0)return 1;
    long long unsigned int aa = 1,bb = 1;
    for(int i=b;i>0;i--,a--){
        aa*= a;bb*=i;
        int gc = gcd(aa,bb);
        if(gc > 1){aa/=gc;bb/=gc;}
        }
    return aa % 1000000007;
    }
bool isprime(long long unsigned int n){
    //cout << sqrt(n) << endl;
    for(int i=2;i<=sqrt(n);i++)
        if(n%i == 0)return false;
    return true;
    }
int b[101][100005];
int main()
{
    int n,m;
    int s[105];
    int d[105][105];
    int dd[105][105];
    int ss[105][105];
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++){
        scanf("%d",&s[i]);
        ss[i][0] = 0;
        for(int j=0;j<s[i];j++){
            scanf("%d",&d[i][j]);
            ss[i][j+1] = ss[i][j] + d[i][j];
        }
        for(int j=0;j<=s[i];j++)
            for(int k=0;k<=j;k++)
                dd[i][j] = max(dd[i][j], ss[i][k]+ss[i][s[i]]-ss[i][s[i]-j+k]);
        }
    for(int i=0;i<n;i++){
        for(int j=0;j<=s[i];j++)
            cout << dd[i][j] << " ";
        cout << endl;}
    for(int i=0;i<n;i++)
        for(int j=0;j<=m;j++)
            b[i][j] = 0;
    for(int j=0;j<=m;j++)
        if(j<=s[0])b[0][j] = dd[0][j];
        else b[0][j] = -1000000;
    for(int i=1;i<n;i++)
        for(int j=0;j<=m;j++)
            for(int k=0;k<=s[i];k++)
                if(j>=k)b[i][j] = max(b[i][j],dd[i][k]+b[i-1][j-k]);
    cout << b[n-1][m];
    return 0;
}


#include<bits/stdc++.h>
#define MAXN 100009
#define INF 1000000007
#define LLINF 1000000000000000007
#define mp(x,y) make_pair(x,y)
#define wr cout<<"Continue Debugging!!!"<<endl;
#define ff first
#define ss second
#define lg(x) ceil(log2(x))
#define all(x) x.begin(),x.end()
#define pb(x) push_back(x)
#define ppb() pop_back()
#define tr(i, c) for(typeof((c).begin()) i = (c).begin(); i!=(c).end(); i++)
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
template<class T> bool umin(T& a, T b) { if(a > b){ a = b;return 1;}return 0;}
template<class T> bool umax(T& a, T b) { if(a < b){ a = b;return 1;}return 0;}
//freopen(".in", "r", stdin);
//freopen(".out", "w", stdout);
int arr[MAXN],cp[MAXN],dp[109][10009];
int main(){
	int n,m,x;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		fill(cp,cp+109,0);
		scanf("%d",&x);
		for(int j=1;j<=x;j++)
			scanf("%d",arr+j),arr[j]+=arr[j-1];
		for(int j=1;j<=x;j++)
			for(int k=0;k<=j;k++)
				umax(cp[j],arr[k]+arr[x]-arr[x-j+k]);
		for(int j=1;j<=m;j++)
			for(int k=0;k<=j;k++)
				umax(dp[i][j],dp[i-1][k]+cp[j-k]);
	}
	cout<<dp[n][m]<<endl;
	return 0;
}


#include<bits/stdc++.h>
#define MAXN 100009
#define INF 1000000007
#define LLINF 1000000000000000007
#define mp(x,y) make_pair(x,y)
#define wr cout<<"Continue Debugging!!!"<<endl;
#define ff first
#define ss second
#define lg(x) ceil(log2(x))
#define all(x) x.begin(),x.end()
#define pb(x) push_back(x)
#define ppb() pop_back()
#define tr(i, c) for(typeof((c).begin()) i = (c).begin(); i!=(c).end(); i++)
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
template<class T> bool umin(T& a, T b) { if(a > b){ a = b;return 1;}return 0;}
template<class T> bool umax(T& a, T b) { if(a < b){ a = b;return 1;}return 0;}
//freopen(".in", "r", stdin);
//freopen(".out", "w", stdout);
int arr[MAXN],cp[10010],dp[109][10009];
int main(){
	int n,m,x;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		memset(cp,0,sizeof(cp));
		scanf("%d",&x);
		for(int j=1;j<=x;j++)
			scanf("%d",arr+j),arr[j]+=arr[j-1];
		for(int j=1;j<=x;j++)
			for(int k=0;k<=j;k++)
				umax(cp[j],arr[k]+arr[x]-arr[x-j+k]);
		for(int j=1;j<=m;j++)
			for(int k=max(j-x,0);k<=j;k++)
				umax(dp[i][j],dp[i-1][k]+cp[j-k]);
	}
	cout<<dp[n][m]<<endl;
	return 0;
}