传送门:http://codeforces.com/problemset/problem/567/E
思路:正着做一遍最短路,反着做一遍最短路,然后就可以判断一条边是否在最短路径图上了
设这条边为从a到b权值为c,那么如果dis[st][a]+c+dis[b][ed]=mindis,则在最短路径图上。
如果一条边是最短路图的桥,那么这就是必经边,
对于非必经边,就看减到多少才会使dis[st][a]+c+dis[b][ed]<mindis,
如果小于0,输NO,否则这条路就可修。
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define PI pair<ll,ll>
#define mp(a,b) make_pair(a,b)
#define fi first
#define se second
const int maxn=200010,maxm=400010,maxq=maxn*5;
using namespace std;
typedef long long ll;
ll n,m,st,ed,pre[3][maxm],now[3][maxn],son[3][maxm],val[3][maxm],frm[3][maxm],tot[3];
ll q[maxq+10],head,tail,top;ll dis[3][maxn],mindis,ans[maxm];
bool bo[maxn],must[maxn],ins[maxn],in[maxm],use[maxm];//must 一定在最短路上,in在最短路图上
ll tim,dfn[maxn],low[maxn],bcnt,bel[maxn];
void add(ll a,ll b,ll c,ll id){
pre[id][++tot[id]]=now[id][a];
now[id][a]=tot[id];
frm[id][tot[id]]=a;
son[id][tot[id]]=b;
val[id][tot[id]]=c;
}
bool operator >(PI a,PI b){
if (a.fi!=b.fi) return a.fi<b.fi;
return a.se<b.se;
}
/*void spfa(ll c){
memset(dis[c],63,sizeof(dis[c]));
memset(bo,0,sizeof(bo));
if (!c) q[tail=1]=st,bo[st]=1,dis[c][st]=0;
else q[tail=1]=ed,bo[ed]=1,dis[c][ed]=0;
head=0;
while (head!=tail){
if (++head>maxq) head=1;
ll x=q[head];
for (ll y=now[c][x];y;y=pre[c][y]){
ll xx=son[c][y];
if (dis[c][xx]>dis[c][x]+val[c][y]){
dis[c][xx]=dis[c][x]+val[c][y];
if (!bo[xx]){
if (++tail>maxq) tail=1;
q[tail]=xx,bo[xx]=1;
}
}
}
bo[x]=0;
}
if (!c) mindis=dis[c][ed];
//printf("%d\n",mindis);
}*/
bool cmp(PI a,PI b){return a>b;}
void dijkstra(ll c){
memset(dis[c],63,sizeof(dis[c]));
//memset(bo,0,sizeof(bo));
priority_queue< PI,vector<PI>,greater<PI> > q;
if (!c) q.push(mp(0,st)),dis[c][st]=0;
else q.push(mp(0,ed)),dis[c][ed]=0;
while (!q.empty()){
ll x=q.top().se,d=q.top().fi;
q.pop();
for (ll y=now[c][x];y;y=pre[c][y]){
ll xx=son[c][y];
if (dis[c][xx]>d+val[c][y]){
dis[c][xx]=d+val[c][y];
q.push(mp(dis[c][xx],xx));
}
}
}
if (!c) mindis=dis[c][ed];
//printf("%d\n",mindis);
}
void rebuild(){
for (ll i=1;i<=m;i++){
ll a=frm[0][i],b=son[0][i],c=val[0][i];
if (dis[0][a]+dis[1][b]+c==mindis)
in[i]=1,add(a,b,c,2),add(b,a,c,2);
}
}
void tarjan(ll x,ll fa){
dfn[x]=low[x]=++tim,q[++top]=x,ins[x]=1;
for (ll y=now[2][x];y;y=pre[2][y]){
if (use[y]) continue;
ll xx=son[2][y];
use[y]=use[y^1]=1;
if (!dfn[xx]) tarjan(xx,x),low[x]=min(low[x],low[xx]);
else if (ins[xx]) low[x]=min(low[x],dfn[xx]);
}
if (low[x]==dfn[x]){
ll xx;bcnt++;
do{
xx=q[top--],bel[xx]=bcnt,ins[xx]=0;
}while (xx!=x);
}
}
void work(){
for (ll i=1;i<=m;i++){
if (!in[i]) continue;
ll a=frm[0][i],b=son[0][i];
if (bel[a]!=bel[b]) must[i]=1;
}
for (ll i=1;i<=m;i++){
if (must[i]) continue;
ll a=frm[0][i],b=son[0][i];
ans[i]=mindis-dis[0][a]-dis[1][b]-1;
}
for (ll i=1;i<=m;i++){
if (must[i]) puts("YES");
else if (ans[i]>0) printf("CAN %I64d\n",val[0][i]-ans[i]);
else puts("NO");
}
}
int main(){
scanf("%I64d%I64d%I64d%I64d",&n,&m,&st,&ed);tot[2]=1;
for (ll i=1,a,b,c;i<=m;i++) scanf("%I64d%I64d%I64d",&a,&b,&c),add(a,b,c,0),add(b,a,c,1);
dijkstra(0),dijkstra(1),rebuild(),tarjan(st,0),work();
return 0;
}