#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<ll, int>;
int ctoi(char c) {
  if (c == 'R') {
    return 0;
  } else if (c == 'G') {
    return 1;
  } else{
    return 2;
  }
}
int main () {
  int N;
  cin >> N;
  P A[200020];
  int cnt[] = {0, 0, 0};
  for (int i = 0; i < N * 2; i ++) {
    ll a;
    char c;
    cin >> a >> c;
    int b = ctoi(c);
    cnt[b] ++;
    A[i] = make_pair(a, b);
  }
  sort(A, A + (N * 2));
  if ((cnt[0] % 2 + cnt[1] % 2 + cnt[2] % 2) == 0) {
    cout << 0 << endl;
    return 0;
  }
  int a = 0;
  while (cnt[a] % 2 == 0) a ++;
  int b = a + 1;
  while (cnt[b] % 2 == 0) b ++;
  ll inf = 1e8 + 8;
  inf = inf * inf;
  ll ans = inf;
  //cout << a << ' ' << b << endl;
  ll mim[] = {-inf, -inf, -inf};
  int re = 3 - a - b;
  ll ans1 = inf;
  ll ans2 = inf;
  for (int i = 0; i < N * 2; i ++) {
    ll p;
    int q;
    tie(p, q) = A[i];
    mim[q] = p;
    if (q == re) {
      ans1 = min(ans1, p - mim[a]);
      ans2 = min(ans2, p - mim[b]);
    } else if (q == a) {
      ans1 = min(ans1, p - mim[re]);
      ans = min(ans, p - mim[b]);
    } else {
      ans2 = min(ans2, p - mim[re]);
      ans = min(ans, p - mim[a]);
    }
  }
  ans = min(ans, ans1 + ans2);
  cout << ans << endl;
}
#define _USE_MATH_DEFINES
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include <cassert>
#include <numeric>
#include <unordered_map>
#include <queue>
#include <math.h>
#include <climits>
#include <set>
#include <map>
using namespace std;

using ll = long long;
using ld = long double;
using pll = pair<ll, ll>;
using pdd = pair<ld, ld>;
//template<class T> using pq = priority_queue<T, vector<T>, greater<T>>;

#define FOR(i, a, b) for(ll i=(a); i<(b);i++)
#define REP(i, n) for(ll i=0; i<(n);i++)
#define ROF(i, a, b) for(ll i=(b-1); i>=(a);i--)
#define PER(i, n) for(ll i=n-1; i>=0;i--)
#define REPREP(i,j,a,b) for(ll i=0;i<a;i++)for(ll j=0;j<b;j++)
#define VV(type) vector< vector<type> >
#define VV2(type,n,m,val) vector< vector<type> > val;val.resize(n);for(ll i;i<n;i++)val[i].resize(m)
#define vec(type) vector<type>
#define VEC(type,n,val) vector<type> val;val.resize(n)
#define VL vector<ll>
#define VVL vector< vector<ll> >
#define SZ size()
#define all(i) begin(i),end(i)
#define SORT(i) sort(all(i))
#define BITI(i) (1<<i)
#define BITSET(x,i) x | (1<<i)
#define BITCUT(x,i) x & ~(1<<i)
#define EXISTBIT(x,i) ((x>>i) & 1 != 0)
#define ALLBIT(n) (1<<n-1)

class UndirectedGraph {
public:
  struct edge { ll to,cost; };  // 行先,容量,逆容量,コスト

  UndirectedGraph(ll n) {
    edges.resize(n);
  }
  void addEdge(ll from, ll to, ll cost) {
    edge eF = { to,cost };
    edges[from].push_back(eF);
    edge eT = { from,cost };
    edges[to].push_back(eT);
  }

  void FindConnect(ll v, vector<bool>& out) {
    out.assign(edges.size(), false);
    vector<ll> stack;
    stack.push_back(v);
    out[v] = true;
    while (!stack.empty()) {
      v = stack.back(); stack.pop_back();
      for (int i = 0; i < edges[v].size(); i++) {
        ll t = edges[v][i].to;
        if (!out[t]) {
          out[t] = true;
          stack.push_back(t);
        }
      }
    }
  }
  vector<vector<edge>> edges;
};

int main() {
  ll n, m;
  cin >> n >> m;
  VL a(m), b(m), c(m);
  UndirectedGraph g(n);

  REP(i, m) {
    char cc;
    cin >> a[i] >> b[i] >> cc;
    a[i]--; b[i]--;
    c[i] = cc - 'a';
    g.addEdge(a[i], b[i], c[i]);
  }
  
  queue<tuple<ll, ll, ll>> que;
  vector<vector<bool>> used(n);
  REP(i, n) {
    used[i].assign(n, false);
  }
  que.push({ 0,0,n - 1 });
  used[0][n - 1] = true;
  used[n - 1][0] = true;

  ll find = -1;
  while (!que.empty()) {
    auto [dist, l, r] = que.front();
    que.pop();
    if (find != -1 && find < dist) {
      cout << find * 2 + 1;
      return 0;
    }
    if (l == r) {
      cout << dist * 2;
      return 0;
    }
    REP(i, g.edges[l].size()) {
      REP(j, g.edges[r].size()) {
        if (g.edges[l][i].cost == g.edges[r][j].cost) {
          if (g.edges[l][i].to == r && g.edges[r][j].to == l) {
            find = dist;
            continue;
          }
          if (used[g.edges[l][i].to][g.edges[r][j].to])
            continue;
          que.push({ dist + 1,g.edges[l][i].to ,g.edges[r][j].to });
          used[g.edges[l][i].to][g.edges[r][j].to] = true;
          used[g.edges[r][j].to][g.edges[l][i].to] = true;
        }
      }
    }
  }
  if (find != -1) {
    cout << find * 2 + 1;
    return 0;
  }
  cout << -1;
}
