Stamp Rally

Stamp Rally

The Japan Amusement Group (JAG) is planning an event at a theme park that imitates an island country. In this event, each time a participant crosses a bridge, the stamps decided for each bridge are stamped in order on the stamp book. The prepared stamp is one of the following seven types.


a () [] + *

It is clear if you walk across the bridge from the start to the goal and the sequence of stamps stamped is the correct formula. However, the direction of crossing the bridge is fixed, and it is not possible to cross in the opposite direction. You can cross the same bridge many times, and if you finally reach the goal point, you may continue to collect stamps after reaching the goal point. The correct formula is <expression> defined by BNF below.


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

Since I decided the start goal and the stamp for each bridge, I tried it with the people concerned, but no one appeared to clear it. Perhaps it cannot be cleared with this setting.

Since the start / goal and bridge information is given, write a program to judge whether it can be cleared.

Input

The input consists of 50 or less datasets. Each data set is represented in the following format.

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

The first line of the dataset consists of four integers n, m, s, and t separated by a single whitespace character. n is the number of islands, and we can assume that 1 ≤ n ≤ 200. Each island is numbered from 1 to n. m is the number of bridges and we can assume that 1 ≤ m ≤ 100,000. s is the starting island number and t is the goal island number. Sometimes the start and finish are on the same island. Each of the following m lines consists of two integers separated by one space character and one character. ai and bi represent the crossing from island ai to island bi by the i-th bridge, and ci represents the stamp stamped by the i-th bridge. There may be multiple bridges between two islands, or there may be bridges within one island.

The end of the input is indicated by a single line of four zeros.

Output

For each dataset, output "Yes" if it can be cleared, and "No" if it cannot be cleared on one line.

Sample Input


4 5 1 4
1 2 (
1 3 a
2 4 a
3 4)
3 2 +
4 4 1 2
13 (
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 (
twenty one *
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
twenty one (
twenty one )
twenty one [
twenty one ]
2 1 +
twenty one *
0 0 0 0

Output for Sample Input


Yes
No
No
Yes
No





Example

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

Yes
No
No
Yes
No
#include<bits/stdc++.h>
using namespace std;
int n,m,s,t;
int op[200][200];
int fa[200][200];
int fb[200][200];
int fc[200][200];
int fd[200][200];
int num[200][200];
int Anum[200][200];
int Cnum[200][200];
int Onum[200][200];
int numO[200][200];

struct data{
  int from,to,type;
  data(int a,int b,int c):from(a),to(b),type(c){}
};

void init(){
  for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
      op[i][j]=0;
      fa[i][j]=0;
      fb[i][j]=0;
      fc[i][j]=0;
      fd[i][j]=0;
      num[i][j]=0;
      Anum[i][j]=0;
      Cnum[i][j]=0;
      Onum[i][j]=0;
    }
  }
}

bool solve(){
  queue< data > Q;
  for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
      if(num[i][j]==1)
        Q.push(data(i,j,0));
  
  while(!Q.empty()){
    data d=Q.front();Q.pop();
    if(d.from==s&&d.to==t&&d.type==0)return true;
    if(d.type==0){
      for(int nfrom=0;nfrom<n;nfrom++){
        if(op[nfrom][d.from]==1){
          if(Onum[nfrom][d.to]==0){
            Onum[nfrom][d.to]=1;
            Q.push(data(nfrom,d.to,3));
          }
        }
        if(fa[nfrom][d.from]==1){
          if(Anum[nfrom][d.to]==0){
            Anum[nfrom][d.to]=1;
            Q.push(data(nfrom,d.to,1));
          }
        }
        if(fc[nfrom][d.from]==1){
          if(Cnum[nfrom][d.to]==0){
            Cnum[nfrom][d.to]=1;
            Q.push(data(nfrom,d.to,2));
          }
        }
      }
      for(int nto=0;nto<n;nto++){
        if(Onum[d.to][nto]==1){
          if(num[d.from][nto]==0){
            num[d.from][nto]=1;
            Q.push(data(d.from,nto,0));
          }
        }
      }
    }
    if(d.type==1){
      for(int nto=0;nto<n;nto++){
        if(fb[d.to][nto]==1){
          if(num[d.from][nto]==0){
            num[d.from][nto]=1;
            Q.push(data(d.from,nto,0));
          }
        }
      }
    }
    if(d.type==2){
      for(int nto=0;nto<n;nto++){
        if(fd[d.to][nto]==1){
          if(num[d.from][nto]==0){
            num[d.from][nto]=1;
            Q.push(data(d.from,nto,0));
          }
        }
      }
    }
    if(d.type==3){
      for(int nfrom=0;nfrom<n;nfrom++){
        if(num[nfrom][d.from]==1){
          if(num[nfrom][d.to]==0){
            num[nfrom][d.to]=1;
            Q.push(data(nfrom,d.to,0));
          }
        }
      }
    }
  }
  return false;
}

int main(){
  while(1){
    cin>>n>>m>>s>>t;
    if(n==0&&m==0&&s==0&&t==0)break;
    s--,t--;
    init();
    for(int i=0;i<m;i++){
      int from,to;
      string str;
      cin>>from>>to>>str;
      from--,to--;
      if(str=="*"||str=="+"){
        op[from][to]=1;
      }else if(str=="("){
        fa[from][to]=1;
      }else if(str==")"){
        fb[from][to]=1;
      }else if(str=="["){
        fc[from][to]=1;
      }else if(str=="]"){
        fd[from][to]=1;
      }else if(str=="a"){
        num[from][to]=1;
      }
    }
    cout<< (solve()?"Yes":"No") <<endl;
  }
  return 0;
}

