Problem:
Problem I: 夏への扉

なつめは大のねこ好きである。なつめの家ではずっとねこを飼っておらず、ねこ好きななつめはいつも野良ねこと遊んでいた。しかし、今回なつめは決心し、自分の家でねこを一匹飼うことにした。なつめはねこを家に迎え、レノンと名付けてかわいがり始めた。

なつめの家はたくさんの部屋と、それらをつなぐたくさんの扉からなっており、扉は次の2種類がある。

人間用の普通の扉

なつめは開けることができるが、レノンが自分で開けることはできない。なつめとレノンの両方が通ることができる。一度開ければ、その後は開いたままにしておける。

ねこ用の小さな扉

レノンが自分であけて自由に通ることができる。ただし小さいために、なつめが通ることはできない。

レノンは夏が大好きである。だから、冬になり家の外がまっしろな雪で覆われてしまう頃になると、彼の機嫌はとても悪くなってしまった。しかし、彼は家にたくさんあるドアのうち、あるひとつの扉が「夏」へとつながっていると信じているようだった。なつめはその扉を「夏への扉」と呼んでいる。そして、寒くて不機嫌になってくると、レノンはきまってその扉の向こうへ行きたがるのである。

冬のある日、レノンがまた「夏への扉」の奥へ行こうと思い立った。しかし、レノンがひとりで扉を開けて、夏への扉の奥へ行けるとは限らない。その時はもちろん、なつめはレノンの手伝いをしなければならない。つまり、なつめしか開けることの出来ない扉をいくつか開いて、レノンが「夏への扉」の向こう側へ行けるようにしてあげるのだ。

最初、家の中の全ての扉は閉まっている。家の部屋の接続関係、なつめおよびレノンの初期位置が与えられる。なつめとレノンが最適な戦略をとった時、レノンが「夏への扉」の先へいくためになつめが開けなければならない扉の最小数を計算しなさい。

以下の図は、サンプル入力の例を図示したものである。

図: サンプル入力の初期状態

Input

入力の1行目には、部屋の数 n と扉の数 m が1つの空白文字で区切って与えられる。部屋にはそれぞれ 0 から n の番号が割り振られており、0は「夏への扉」の先をあらわす。2行目はなつめが最初にいる部屋の番号とレノンが最初にいる部屋の番号が、1つの空白文字で区切って与えられる。どちらの部屋番号も1以上であり、最初から「夏への扉」の先にいることはない。続く m 行には、m 枚の扉の情報がそれぞれ1行ずつ与えられる。各行はふたつの部屋IDと扉の種類を表す1文字のアルファベットからなり、1つの空白文字で区切られている。扉は指定されたふたつの部屋を繋いでおり、種類はアルファベットが N のとき人間用の普通の扉、L のときねこ用の小さな扉である。扉が同じ部屋同士を繋ぐことはない。部屋IDが0のものを含む扉が「夏への扉」であり、これは入力中に必ずただ1つ存在する。1 <= n, m <= 100000を満たす。

Output

なつめが開けなければならない扉の最小数を、1行で出力せよ。

Notes on Submission

上記形式で複数のデータセットが与えられます。入力データの 1 行目にデータセットの数が与えられます。各データセットに対する出力を上記形式で順番に出力するプログラムを作成して下さい。

Sample Input

2
4 6
1 2
1 2 N
2 3 N
3 4 N
4 1 N
1 4 L
4 0 L
4 6
1 2
1 2 N
2 3 N
3 4 N
4 1 N
1 4 L
4 0 N

Output for the Sample Input

1
3

Solution in C++11 (judge verdict: Accepted)

#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<string>
#include<sstream>
#include<complex>
#include<tuple>

using namespace std;

#define reep(i, s, n) for(int i=s;i<(int)n;i++)
#define rep(i, n) for(int i=0;i<(int)n;i++)
#define REP(i, n) for(int i=0;i<(int)n;i++)
#define all(v) v.begin(), v.end()
#define tyd typedef
#define vc vector
#define pb push_back
#define eb emplace_back
#define mp make_pair

typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> pii;
const int INF = 1<<28;	

int T, n, m, nat, len;

struct UnionFind{
	vector<int> d;
	UnionFind(int n):d(n, -1){}
	bool unite(int x, int y){
		if((x = root(x)) != (y = root(y))){
			if(d[y] < d[x]) swap(x, y);
			d[x] += d[y]; d[y] = x;
		}
		return x != y;
	}
	int root(int x){return d[x] < 0 ? x : d[x] = root(d[x]);}
};

vi bfs(const vector<vi> &g, vi s){
	vi dp(n+1, INF);
	queue<int> q;
	for(int u : s){
		q.push(u);
		dp[u] = 0;
	}
	while(!q.empty()){
		int u = q.front(); q.pop();
		for(int v : g[u])if(dp[u]+1 < dp[v]){
			q.push(v);
			dp[v] = dp[u] + 1;
		}
	}
	return dp;
}


int main(){
	cin >> T;
	while(T--){
		cin >> n >> m >> nat >> len;
		vector<vi> g(n+1);
		UnionFind uf(n+1);
		REP(i, m){
			int u, v; char c;
			cin >> u >> v >> c;
			if(c == 'N'){
				g[u].pb(v);
				g[v].pb(u);
			}else{
				uf.unite(u, v);
			}
		}
		if(uf.root(0) == uf.root(len)){
			puts("0");
			continue;
		}
		vi s1, s2;
		REP(i, n+1) if(uf.root(i) == uf.root(len)) s1.pb(i);
		REP(i, n+1) if(uf.root(i) == uf.root(0)) s2.pb(i);
		auto d1 = bfs(g, s1);
		auto d2 = bfs(g, s2);
		auto d3 = bfs(g, vi({nat}));
		REP(i, n)if(uf.root(i) == 0){
			d1[i] = d1[0];
			d2[i] = d2[0];
			d3[i] = d3[0];
		}
//		cout << "uf: " ;REP(i, n+1) cout << uf.root(i) << ", "; cout << endl;
//		cout << "d1: " ;REP(i, n+1) cout << d1[i] << ", "; cout << endl;
//		cout << "d2: " ; REP(i, n+1) cout << d2[i] << ", "; cout << endl;
//		cout << "d3: " ; REP(i, n+1) cout << d3[i] << ", "; cout << endl;
		int ans = INF;
		REP(i, n) ans = min(ans, d1[i] + d2[i] + d3[i]);
		if(ans < INF) printf("%d\n", ans);
		else puts("-1");
	}
	return 0;
	
}