/**
[最短路] hdu 4360 As long as Binbin loves Sangsang
迪杰斯特拉,只是这里的d数组要扩展的两维,又因要求最短路和最多串,在添加一个长度为2的维度。
自圈很坑,开始做的时候一直卡。。。
其实,只有1上的自圈且只有1一个点的时候比较特殊,特判一下就过了
*/
#include <stdio.h>
#include <string.h>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
#define N 1500
#define M 150000
#define INF 1LL << 50
struct node
{
__int64 d;
int u,wrd,cnt;
node(int x = 0,__int64 a = 0LL,int b = 0,int c = 0)
{
u = x;
d = a;
cnt = b;
wrd = c;
}
};
vector<node> vec[N];
bool operator<(node a,node b)
{
if(a.d == b.d && a.cnt == b.cnt)
return a.wrd < b.wrd;
if(a.d == b.d)
return a.cnt < b.cnt;
return a.d > b.d;
}
int n;
__int64 d[N][4][2];
int vis[N][4];
void addEdge(int u,int v,int c,int w)
{
vec[u].push_back(node(v,0LL,c,w));
}
int relax(int u,int wu,int v,int wv,int c,node &pt)
{
if(d[u][wu][0] + c < d[v][wv][0])
{
d[v][wv][0] = d[u][wu][0] + c;
d[v][wv][1] = d[u][wu][1];
if(wv == 3)
d[v][wv][1] ++;
pt = node(v,d[v][wv][0],d[v][wv][1],wv);
return 1;
}
if(d[u][wu][0] + c == d[v][wv][0])
{
if(wv == 3)
{
if(d[u][wu][1] + 1 > d[v][wv][1])
{
d[v][wv][1] = d[u][wu][1] + 1;
pt = node(v,d[v][wv][0],d[v][wv][1],wv);
return 1;
}
else
return 0;
}
if(d[u][wu][1] > d[v][wv][1])
{
d[v][wv][1] = d[u][wu][1];
pt = node(v,d[v][wv][0],d[v][wv][1],wv);
return 1;
}
return 0;
}
return 0;
}
int dij(__int64 &dis,int &num)
{
int i,j;
for(i = 0; i <= n; ++i)
for(j = 0; j < 4; ++j)
d[i][j][0] = INF,d[i][j][1] = 0;
memset(vis,0,sizeof(vis));
priority_queue<node> que;
node p,pt;
p = node(1,0,0,3);
d[1][3][0] = 0;
que.push(p);
while(!que.empty())
{
p = que.top();
que.pop();
if(vis[p.u][p.wrd])
continue;
vis[p.u][p.wrd] = 1;
int u = p.u,v,wr,c;
for(i = 0; i < vec[u].size(); ++i)
{
v = vec[u][i].u;wr = vec[u][i].wrd;c = vec[u][i].cnt;
if((p.wrd + 1) % 4 == wr)
{
if(!vis[v][wr] && relax(u,p.wrd,v,wr,c,pt))
que.push(pt);//printf("%d,%d,%d\n",pt.u,pt.d,pt.wrd);
}
}
}
for(i = 1; i <= n; ++i)
vec[i].clear();
if(d[n][3][0] == INF || d[n][3][1] == 0LL)
return 0;
dis = d[n][3][0];
num = d[n][3][1];
return 1;
}
int tra[200];
int main()
{
tra[int('L')] = 0;
tra[int('O')] = 1;
tra[int('V')] = 2;
tra[int('E')] = 3;
int m,t,cas = 0,u,v,c,w;
char ww[3];
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
while(m --)
{
scanf("%d%d%d%s",&u,&v,&c,ww);
addEdge(u,v,c,tra[int(ww[0])]);
if(u != v)
addEdge(v,u,c,tra[int(ww[0])]);
}
__int64 dis = 0;
int num = 0,i,j;
if(n == 1)
{
__int64 f[4] = {INF,INF,INF,INF};
for( i = 0; i < vec[1].size(); ++i)
{
j = vec[1][i].wrd;
f[j] = min(f[j],1LL * vec[1][i].cnt);
}
vec[1].clear();
for(i = 0; i < 4 && f[i] != INF; ++i )
dis += f[i];
if(i != 4)
printf("Case %d: Binbin you disappoint Sangsang again, damn it!\n",++cas);
else
printf("Case %d: Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding 1 LOVE strings at last.\n",++cas,dis);
continue;
}
if(dij(dis,num))
printf("Case %d: Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n",++cas,dis,num);
else
printf("Case %d: Binbin you disappoint Sangsang again, damn it!\n",++cas);
}
return 0;
}