Problem:
MathJax.Hub.Config({
tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}
});

Stamp Rally

スタンプラリー

日本アミューズメントグループ (Japan Amusement Group, JAG) では，島国を模したテーマパークでのイベントを企画している．
このイベントでは，参加者は橋を渡るたびに橋ごとに決められたスタンプをスタンプ帳に順番に押していく．
用意されたスタンプは以下の7種類のどれかである．

a ( ) [ ] + *

スタートからゴールまで橋を渡り歩いて，押されたスタンプの列が正しい数式になればクリアである．
ただし橋を渡る向きは決まっていて，逆向きに渡ることはできない．
同じ橋を何度も渡ってよく，最終的にゴール地点に到着するのであれば一度ゴール地点に着いた後に引き続きスタンプを集めてもよい．
正しい数式とは以下の BNF で定義される <expression> である．

<expression> ::= <term> | <expression> "+" <term>
<term> ::= <factor> | <term> "*" <factor>
<factor> ::= "a" | "(" <expression> ")" | "[" <expression> "]"

スタート・ゴールと橋ごとのスタンプを決めたので，関係者で試しにやってみたがなかなかクリアする人が現れない．
もしかしたら，この設定ではクリアすることができないのかもしれない．

スタート・ゴールと橋の情報が与えられるので，クリア可能かどうかを判定するプログラムを書きなさい．

Input

入力は50個以下のデータセットからなる．各データセットは以下の形式で表される．

n m s t
a1 b1 c1
...
am bm cm

データセットの最初の行は，空白文字1個で区切られた4個の整数 n, m, s, t からなる．
n は島の数であり， 1 ≤ n ≤ 200 と仮定してよい．
それぞれの島には 1 から n までの番号が付けられている．
m は橋の数であり， 1 ≤ m ≤ 100,000 と仮定してよい．
s はスタートの島の番号， t はゴールの島の番号である．スタートとゴールが同じ島であることもある．
続く m 行のそれぞれは，空白文字1個で区切られた2個の整数と1個の文字からなる．
ai， bi は i 番目の橋によって島 ai から島 bi へ渡れることを表し， ci は i 番目の橋で押すスタンプを表す．ある2つの島の間に複数の橋がかかっていたり，1つの島の中で橋がかかっていたりすることもある．

入力の終わりは，4つのゼロからなる1行で示される．

Output

各データセットに対して，クリアできるならば"Yes"を，できないならば"No"を1行に出力せよ．

Sample Input

4 5 1 4
1 2 (
1 3 a
2 4 a
3 4 )
3 2 +
4 4 1 2
1 3 (
3 4 a
4 1 +
3 2 a
3 4 1 1
1 2 a
2 2 +
2 3 a
3 1 a
5 8 1 5
1 1 [
1 2 (
2 1 *
2 2 a
2 3 a
3 3 )
3 4 ]
4 5 )
2 14 1 1
1 2 a
1 2 (
1 2 )
1 2 [
1 2 ]
1 2 +
1 2 *
2 1 a
2 1 (
2 1 )
2 1 [
2 1 ]
2 1 +
2 1 *
0 0 0 0

Output for Sample Input

Yes
No
No
Yes
No

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

#include <bits/stdc++.h>
#define int long long
using namespace std;

const string TBL = "a()[]+*";
map<pair<int, int>, int> trans;

void solve() {
    int n, m, s, t; cin >> n >> m >> s >> t;
    if (n == 0) exit(0);
    s--; t--;

    vector<vector<vector<bool>>> dp(n, vector<vector<bool>>(n, vector<bool>(9)));
    struct X { int i, j, c; };
    queue<X> q;
    while (m--) {
        int i, j; cin >> i >> j;
        i--; j--;
        char c_; cin >> c_;
        int c = TBL.find(c_);
        if (c == 6) c--;
        if (!dp[i][j][c]) dp[i][j][c] = true, q.push({i, j, c});
    }

    while (!q.empty()) {
        X x = q.front(); q.pop();
        for (int c = 0; c < 9; c++) {
            // (x.i, x.j), (x.j, k) -> (x.i, k)
            if (trans.count({x.c, c})) {
                int c2 = trans[{x.c, c}];
                for (int k = 0; k < n; k++) {
                    if (dp[x.j][k][c] && !dp[x.i][k][c2]) {
                        dp[x.i][k][c2] = true;
                        q.push({x.i, k, c2});
                    }
                }
            }
            // (k, x.i), (x.i, x.j) -> (k, x.j)
            if (trans.count({c, x.c})) {
                int c2 = trans[{c, x.c}];
                for (int k = 0; k < n; k++) {
                    if (dp[k][x.i][c] && !dp[k][x.j][c2]) {
                        dp[k][x.j][c2] = true;
                        q.push({k, x.j, c2});
                    }
                }
            }
        }
    }
    cout << (dp[s][t][0] ? "Yes" : "No") << endl;
}

signed main() {
    trans[{0, 5}] = 6;
    trans[{1, 0}] = 7;
    trans[{3, 0}] = 8;
    trans[{6, 0}] = 0;
    trans[{7, 2}] = 0;
    trans[{8, 4}] = 0;
    while (1) solve();
}