// ※※※ 解答不能 ※※※
// satashun氏.
// https://atcoder.jp/contests/abc175/submissions/15869137
// -> 一部改変(備忘のためのメモなど追記).
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using P = pair<int, int>;
using Data = pair<LL, P>; // {cost, (direction, string id)}
#define repex(i, a, b, c) for(int i = a; i < b; i += c)
#define repx(i, a, b) repex(i, a, b, 1)
#define rep(i, n) repx(i, 0, n)
#define repr(i, a, b) for(int i = a; i >= b; i--)
#define pb push_back
#define a first
#define b second
#define all(x) x.begin(), x.end()
const LL INF = 202020202020202020;

int main(){
    int N;
    scanf("%d", &N);
    vector<string> S(N);
    vector<LL> C(N);
    map<string, int> sid;
    sid[""] = 0; // goal
    rep(i, N){
        char s[55];
        scanf("%s %lld", s, &C[i]);
        S[i] = s;
        int l = S[i].size();
        
        // 部分文字列(左側からスタート)を, マップに登録.
        string ls;
        rep(j, l){
            ls.pb(S[i][j]);
            if(!sid.count(ls)) sid[ls] = sid.size();
        }
        
        // 部分文字列(右側からスタート)を, マップに登録.
        string rs;
        repr(j, l - 1, 0){
            rs = S[i][j] + rs;
            if(!sid.count(rs)) sid[rs] = sid.size();
        }
    }
    
    int sz = sid.size();
    vector<string> tos(sz);  // 逆引き: 番号 -> 文字列.
    vector<bool> is_pal(sz); // 回文判定.
    for(auto p : sid){
        tos[p.b] = p.a;
        auto t = p.a;
        reverse(all(t));
        is_pal[p.b] = (t == p.a);
    }
    
    vector<vector<LL>> d(2, vector<LL>(sz, INF));
    priority_queue<Data, vector<Data>, greater<Data>> pq;
    LL ans = INF;
    rep(i, N){
        auto t = S[i];
        reverse(all(t));
        // 入力文字列が, すでに回文である場合は, コストが確定するので, 最小コスト(ans)を更新.
        if(S[i] == t){
            ans = min(ans, C[i]);
            continue;
        }
        // この処理は, 何を目的にしているか？
        // -> 要するに, 入力文字列 S[i] が 回文で無い場合は, 回文へ到達するまでに, 
        // 少なくとも, コスト C[i] を 使うために保存？
        int id = sid[S[i]];
        rep(j, 2){
            if(d[j][id] > C[i]){
                d[j][id] = C[i];
                pq.push(make_pair(C[i], make_pair(j, id)));
            }
        }
    }
    
    // ダイクストラ法 を 適用.
    while(!pq.empty()){
        auto data = pq.top();
        pq.pop();
        int dir, id;
        tie(dir, id) = data.b;
        if(d[dir][id] < data.a) continue;
        // 探索毎に, すべての文字列 S[i] を 確認.
        rep(i, N){  // another side
            string s = tos[id], t = S[i];
            if(dir) swap(s, t);  // s:left, t:right
            int sl = s.size(), tl = t.size();
            // 回文判定処理.
            int l = 0;
            while(l < min(sl, tl)){
                if(s[l] == t[tl - 1 - l]) l++;
                else                      break;
            }
            // NG
            if(l < min(sl, tl)) continue;
            LL nd = d[dir][id] + C[i];
            if(l == sl && l == tl){
                ans = min(ans, nd); // 回文に到達した場合.
            }else if(l == sl){
                string rem = t.substr(0, tl - l); // 右側.
                int nid = sid[rem];
                if(is_pal[nid]) ans = min(ans, nd); // 回文に到達した場合.
                if(d[1][nid] > nd){
                    d[1][nid] = nd;
                    pq.push(make_pair(nd, make_pair(1, nid)));
                }
            }else{
                string rem = s.substr(l, s.size() - l); // 左側.
                int nid = sid[rem];
                if(is_pal[nid]) ans = min(ans, nd); // 回文に到達した場合.
                if(d[0][nid] > nd){
                    d[0][nid] = nd;
                    pq.push(make_pair(nd, make_pair(0, nid)));
                }
            }
        }
    }
    if(ans == INF) puts("-1");
    else           printf("%lld\n", ans);
    return 0;
}

Measured memory_bytes: 4016