#pragma GCC optimize("Ofast")
#define _USE_MATH_DEFINES
#include "bits/stdc++.h"

using namespace std;

using ll = int64_t;
using db = double;
using ld = long double;
using vi = vector<int>;
using vl = vector<ll>;
using vvi = vector<vector<int>>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vpii = vector<pii>;
using vpll = vector<pll>;

constexpr char newl = '\n';
constexpr double eps = 1e-10;

#define FOR(i,a,b) for (int i = (a); i < (b); i++)
#define F0R(i,b) FOR(i,0,b)
#define RFO(i,a,b) for (int i = ((b)-1); i >=(a); i--)
#define RF0(i,b) RFO(i,0,b)
#define show(x) cout << #x << " = " << (x) << '\n';
#define rng(a) a.begin(),a.end()
#define rrng(a) a.rbegin(),a.rend()
#define sz(x) (int)(x).size()
#define YesNo {cout<<"Yes";}else{cout<<"No";}
#define YESNO {cout<<"YES";}else{cout<<"NO";}
#define v(T) vector<T>
#define vv(T) vector<vector<T>>

template<typename T1, typename T2> inline void chmin(T1& a, T2 b) { if (a > b) a = b; }
template<typename T1, typename T2> inline void chmax(T1& a, T2 b) { if (a < b) a = b; }
template<class T> bool lcmp(const pair<T, T>& l, const pair<T, T>& r) {
  return l.first < r.first;
}
template<class T> istream& operator>>(istream& i, v(T)& v) {
  F0R(j, sz(v)) i >> v[j];
  return i;
}
template<class A, class B> istream& operator>>(istream& i, pair<A, B>& p) {
  return i >> p.first >> p.second;
}
template<class A, class B, class C> istream& operator>>(istream& i, tuple<A, B, C>& t) {
  return i >> get<0>(t) >> get<1>(t) >> get<2>(t);
}
template<class T> ostream& operator<<(ostream& o, const pair<T, T>& v) {
  o << "(" << v.first << "," << v.second << ")";
  return o;
}
template<class T> ostream& operator<<(ostream& o, const vector<T>& v) {
  F0R(i, v.size()) {
    o << v[i] << ' ';
  }
  o << newl;
  return o;
}
template<class T> ostream& operator<<(ostream& o, const set<T>& v) {
  for (auto e : v) {
    o << e << ' ';
  }
  o << newl;
  return o;
}
template<class T1, class T2> ostream& operator<<(ostream& o, const map<T1, T2>& m) {
  for (auto& p : m) {
    o << p.first << ": " << p.second << newl;
  }
  o << newl;
  return o;
}

#if 1

int red = 1, gre = 2, blu = 4, all = 7;

// INSERT ABOVE HERE
signed main() {
  cin.tie(0);
  ios_base::sync_with_stdio(false);

  int N, M; cin >> N >> M;
  vvi es(N);
  F0R(i, M) {
    int a, b; cin >> a >> b;
    a--; b--;
    es[a].push_back(b);
    es[b].push_back(a);
  }
  ll re = 1;
  v(bool) vs(N);
  F0R(i, N) {
    if (vs[i]) continue;
    vi as;  // 連結になっている頂点リスト
    auto arrange = [&](auto arrange, int v)->void {
      vs[v] = true;
      as.push_back(v);
      for (auto to : es[v]) {
        if (!vs[to]) {
          arrange(arrange, to);
        }
      }
    };
    arrange(arrange, i);
    vi cs(N, 0);
    auto calc = [&](auto calc, int ai)->ll {
      if (ai == sz(as)) return 1;
      int v = as[ai], a = 0;
      for (auto to : es[v]) {
        a |= cs[to];
      }
      ll re = 0;
      F0R(c, 3) {
        if ((a >> c) & 1) continue;
        cs[v] = 1 << c;
        re += calc(calc, ai+1);
      }
      cs[v] = 0;
      return re;
    };
    re *= calc(calc, 0);
  }
  cout << re << newl;
}
#endif

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

const int N = 2e3+5 ;

int n ,m ,u ,v ;
char ch ;
vector<int> adj[128][N] ;
bool edge[N][N] ;
long long dis[N][N] ;
long long bfs(){
    long long ret = 1e18 ;
    memset(dis,'?',sizeof dis);
    queue<pair<int,int>> q ;
    q.push({1,n});
    dis[1][n] = 0 ;
    while(q.size()){
        int a = q.front().first ;
        int b = q.front().second ;
        q.pop() ;
        if(a==b){
            ret = min(ret ,dis[a][b]*2);
            continue ;
        }
        if(edge[a][b]){
            ret = min(ret ,dis[a][b]*2+1);
            continue ;
        }
        for(int ch='a';ch<='z';++ch){
            if(!adj[ch][a].size() || !adj[ch][b].size()) continue ;
            for(int i:adj[ch][a]) for(int j:adj[ch][b]){
                long long to = dis[a][b]+1 ;
                if(dis[i][j]<=to) continue ;
                dis[i][j] = to ;
                if(i==j){
                    ret = min(ret,to*2) ;
                    continue ;
                }
                if(edge[i][j]){
                    ret = min(ret,to*2+1) ;
                    continue ;
                }
                q.push({i,j});
            }
        }
    }
    if(ret>1e9) ret = -1 ;
    return ret ;
}
int main(){
    scanf("%d%d",&n,&m);
    while(m--){
        scanf("%d%d %c",&u,&v,&ch);
        edge[u][v] = edge[v][u] = 1 ;
        adj[ch][u].push_back(v);
        adj[ch][v].push_back(u);
    }
    printf("%lld",bfs());
    return 0;
}
