import sys
from heapq import heappush, heappop
def input(): return sys.stdin.readline().strip()


def main():
    """
    回文文字列を左右からそれぞれ構成していく。
    左の文字列と右の文字列のうち短い方に文字を足していく。
    例えば左に文字列をくっつけたとすると、一般に左側が数文字余る。
    この数文字が回文になっていれば全体も回文。
    そうでなければ左側の余り文字列を含むようないい文字列を右側にくっつければ良い。

    この手法だと回文が生成可能かどうかが多項式時間で判定可能。
    なぜなら左右を見て余る文字列はS1,...,SNのprefixないしsuffixに限定されるから。

    最後にコスト最小の回文をどう発見するかだが、これは余った文字列の状態を頂点とする
    グラフを構成してダイクストラをすれば良い。
    """
    N = int(input())
    string = []
    cost = []
    for _ in range(N):
        s, c = input().split()
        string.append(s)
        cost.append(int(c))
    length = [len(string[i]) for i in range(N)]

    # グラフ頂点の構成（余りなしの文字列の状態をn = 0番目とする）
    # string_to_id[d][i][j] = (Siの先頭(d=0)もしくは末尾(d=1)からj文字とった部分文字列)
    string_to_id = [[[0] * (length[i] + 1) for i in range(N)] for _ in range(2)]
    id_to_string = {}  # id_to_string[id] = (d, i, j)
    n = 1
    for d in range(2):
        for i in range(N):
            for j in range(1, length[i] + 1):
                string_to_id[d][i][j] = n
                id_to_string[n] = (d, i, j)
                n += 1
    #print("n={}".format(n))
    #print("string_to_id={}".format(string_to_id))
    #print("id_to_string={}".format(id_to_string))

    # グラフ辺の構成
    repn = [[] for _ in range(n)]
    for i in range(N):
        repn[0].append((string_to_id[0][i][length[i]], cost[i]))
        repn[0].append((string_to_id[1][i][length[i]], cost[i]))
    for v in range(1, n):
        d, i, j = id_to_string[v]
        if d == 0:
            # 先頭が余っている＝右の文字列が長い場合
            for ni in range(N):
                if j <= length[ni]:
                    # 左に文字列を追加して左側が長くなる場合
                    if string[ni][:j] != (string[i][:j])[::-1]: continue
                    id = string_to_id[1][ni][length[ni] - j]
                else:
                    # 左側に文字列を追加してもまだ右側が長い場合
                    if string[ni] != (string[i][(j - length[ni]):j])[::-1]: continue
                    id = string_to_id[0][i][j - length[ni]]
                repn[v].append((id, cost[ni]))
        else:
            # 末尾が余っている＝左の文字列が長い場合
            for ni in range(N):
                if j <= length[ni]:
                    # 右に文字列を追加して右側が長くなる場合
                    if (string[i][-j:])[::-1] != string[ni][-j:]: continue
                    id = string_to_id[0][ni][length[ni] - j]
                else:
                    # 右側に文字列を追加してもまだ左側が長い場合
                    if (string[i][-j:(-j + length[ni])])[::-1] != string[ni]: continue
                    id = string_to_id[1][i][j - length[ni]]
                repn[v].append((id, cost[ni]))
        #print("repn[{}]={}".format(v, repn[v]))


    # ダイクストラ（キューの中身は辺のコストじゃなくてそこまでの合計コストですよ！！！！！！）
    # あとキューに入れる時に距離を確定（「コスト最初距離候補」ではなく「距離確定の中の最小」から進めるから）
    min_cost = [10**18] * n
    q = []  # (qの中身)＝(dist, to)
    for v, cos in repn[0]:
        min_cost[v] = cos
        heappush(q, (cos, v))
    while q:
        dist, v = heappop(q)
        if min_cost[v] != dist: continue  # 枝刈り１回目
        for nv, ncos in repn[v]:
            if min_cost[nv] <= dist + ncos: continue  # 枝刈り２回目
            min_cost[nv] = dist + ncos
            heappush(q, (dist + ncos, nv))
    #for v in range(n): print("min_cost[{}]={}".format(v, min_cost[v]))

    # 最小コストを探索
    ans = 10**18
    ans = min(ans, min_cost[0])  # きれいに終わる場合を忘れてた
    for v in range(1, n):
        d, i, j = id_to_string[v]
        if d == 0:
            substring = string[i][:j]
        else:
            substring = string[i][-j:]
        if substring == substring[::-1]:
            ans = min(ans, min_cost[v])

    if ans == 10**18:
        print(-1)
    else:
        print(ans)


if __name__ == "__main__":
    main()


Measured memory_bytes: 76004