#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 100
#define BASE 480
#define MAX 600

enum Type{
	A,
	B,
};

struct Edge{
	Edge(int arg_to,int arg_cost,int arg_start_time,int arg_arrive_time){
		to = arg_to;
		cost = arg_cost;
		start_time = arg_start_time;
		arrive_time = arg_arrive_time;
	}
	bool operator<(const struct Edge &arg) const{ //出発時刻の昇順
		return start_time < arg.start_time;
	}
	int to,cost,start_time,arrive_time;
};

struct Info{
	Info(int arg_node_id,int arg_sum_cost,int arg_current_time){
		node_id = arg_node_id;
		sum_cost = arg_sum_cost;
		current_time = arg_current_time;
	}
	bool operator<(const struct Info &arg) const{ //総コストの昇順(PQ)
		return sum_cost > arg.sum_cost;
	}
	int node_id,sum_cost,current_time;
};

struct Data{
	Data(int arg_rev_start_time,int arg_sum_cost){
		rev_start_time = arg_rev_start_time;
		sum_cost = arg_sum_cost;
	}
	bool operator<(const struct Data &arg) const{ //帰宅開始時刻の昇順
		return rev_start_time < arg.rev_start_time;
	}
	int rev_start_time,sum_cost;
};

int N;
int node_index;
int min_cost[2][NUM][601],return_min_cost[NUM][601];
int A_id,B_id;
vector<int> work[2][NUM];
vector<Data> return_start[NUM];
const string start_A = "Hakodate";
const string start_B = "Tokyo";

map<string,int> MAP;
map<int,int> CALC;
vector<Edge> G[NUM];

//時刻を分に直す
int getNUM(char work[6]){

	int hour = 10*(work[0]-'0')+(work[1]-'0');
	int minute = 10*(work[3]-'0')+(work[4]-'0');

	return 60*hour+minute;
}

//8時～18時の時間帯か
bool rangeCheck(int tmp_time){
	if(tmp_time >= BASE && tmp_time <= BASE+MAX)return true;
	else{
		return false;
	}
}

void dijkstra(Type type,int start_id){

	for(int i = 0; i < node_index; i++){
		for(int k = 0; k <= MAX; k++){
			min_cost[type][i][k] = BIG_NUM;
		}
	}

	min_cost[type][start_id][0] = 0; //8時に出発

	priority_queue<Info> Q;
	Q.push(Info(start_id,0,BASE));

	int next_node,next_cost,next_time;

	while(!Q.empty()){

		if(Q.top().sum_cost > min_cost[type][Q.top().node_id][Q.top().current_time-BASE]){
			Q.pop();
		}else{

			for(int i = 0; i < G[Q.top().node_id].size(); i++){
				//既に出発している、または有効時間外ならSKIP
				if(Q.top().current_time > G[Q.top().node_id][i].start_time)continue;
				if(rangeCheck(G[Q.top().node_id][i].start_time) == false || rangeCheck(G[Q.top().node_id][i].arrive_time) == false)continue;

				next_node = G[Q.top().node_id][i].to;
				next_cost = Q.top().sum_cost+G[Q.top().node_id][i].cost;
				next_time = G[Q.top().node_id][i].arrive_time;

				if(min_cost[type][next_node][next_time-BASE] > next_cost){

					min_cost[type][next_node][next_time-BASE] = next_cost;
					Q.push(Info(next_node,next_cost,next_time));
				}
			}
			Q.pop();
		}
	}
}

int rev_dijkstra(int start_id){

	int ret = BIG_NUM;
	int next_node,next_cost,next_time;
	int A_min,B_min;
	priority_queue<Info> Q;

	for(int p = 0; p < return_start[start_id].size(); p++){ //start時刻を全探索

		int start_time = return_start[start_id][p].rev_start_time;
		int start_cost = return_start[start_id][p].sum_cost;

		for(int a = 0; a < node_index; a++){
			for(int k = start_time-BASE; k <= MAX; k++)return_min_cost[a][k] = BIG_NUM;
		}

		return_min_cost[start_id][start_time-BASE] = 0; //★帰宅のコスト
		Q.push(Info(start_id,0,start_time));

		A_min = BIG_NUM;
		B_min = BIG_NUM;

		while(!Q.empty()){

			if(Q.top().sum_cost > return_min_cost[Q.top().node_id][Q.top().current_time-BASE]){
				Q.pop();
			}else{

				for(int i = 0; i < G[Q.top().node_id].size(); i++){
					//既に出発している、または有効時間外ならSKIP
					if(Q.top().current_time > G[Q.top().node_id][i].start_time)continue;
					if(rangeCheck(G[Q.top().node_id][i].start_time) == false || rangeCheck(G[Q.top().node_id][i].arrive_time) == false)continue;

					next_node = G[Q.top().node_id][i].to;
					next_cost = Q.top().sum_cost+G[Q.top().node_id][i].cost;
					next_time = G[Q.top().node_id][i].arrive_time;

					if(return_min_cost[next_node][next_time-BASE] > next_cost){
						return_min_cost[next_node][next_time-BASE] = next_cost;

						Q.push(Info(next_node,next_cost,next_time));
					}
				}
				Q.pop();
			}
		}

		for(int time = start_time-BASE; time <= MAX; time++){
			if(return_min_cost[A_id][time] != BIG_NUM){
				A_min = min(A_min,return_min_cost[A_id][time]);
			}
			if(return_min_cost[B_id][time] != BIG_NUM){
				B_min = min(B_min,return_min_cost[B_id][time]);
			}
		}

		if(A_min == BIG_NUM || B_min == BIG_NUM)continue;

		ret = min(ret,start_cost+A_min+B_min);
	}
	return ret;
}

void func(){

	MAP.clear();
	for(int i = 0; i < NUM; i++)G[i].clear();

	node_index = 0;

	string start,arrival;
	char start_buf[6],arrive_buf[6];
	int start_time,arrive_time;
	int price,start_id,arrive_id;

	for(int loop = 0; loop < N; loop++){
		cin >> start >> start_buf >> arrival >> arrive_buf >> price;

		auto at = MAP.find(start);

		if(at == MAP.end()){
			MAP[start] = node_index;
			start_id = node_index;
			node_index++;

		}else{
			start_id = MAP[start];
		}

		at = MAP.find(arrival);

		if(at == MAP.end()){
			MAP[arrival] = node_index;
			arrive_id = node_index;
			node_index++;

		}else{
			arrive_id = MAP[arrival];
		}

		start_time = getNUM(start_buf);
		arrive_time = getNUM(arrive_buf);

		if(rangeCheck(start_time) == false || rangeCheck(arrive_time) == false)continue;

		G[start_id].push_back(Edge(arrive_id,price,start_time,arrive_time));
	}

	A_id = MAP[start_A];
	B_id = MAP[start_B];

	//函館、東京から、各都市への到着可能時刻と、同時刻での最小コストを求める
	dijkstra(A,A_id);
	dijkstra(B,B_id);

	for(int town = 0; town < node_index; town++){

		work[A][town].clear();
		work[B][town].clear();

		return_start[town].clear();
	}

	int rev_start_time,tmp_cost;

	//各町から、函館or北海道への、帰宅開始可能時刻をworkにpushする
	for(int town = 0; town < node_index; town++){
		for(int time = 0; time <= MAX; time++){

			if(min_cost[A][town][time] != BIG_NUM){
				work[A][town].push_back(time+BASE);
			}

			if(min_cost[B][town][time] != BIG_NUM){
				work[B][town].push_back(time+BASE);
			}
		}

		//★最低30分会うので、帰宅開始可能時刻と、そのコストを求める★
		if(work[A][town].size() == 0 || work[B][town].size() == 0)continue;

		CALC.clear();

		for(int time = 1; time <= MAX; time++){
			min_cost[A][town][time] = min(min_cost[A][town][time],min_cost[A][town][time-1]);
			min_cost[B][town][time] = min(min_cost[B][town][time],min_cost[B][town][time-1]);
		}

		for(int i = 0; i < work[A][town].size(); i++){
			for(int k = 0; k < work[B][town].size(); k++){
				rev_start_time = max(work[A][town][i],work[B][town][k])+30;
				if(!rangeCheck(rev_start_time))continue;

				auto at2 = CALC.find(rev_start_time);
				tmp_cost = min_cost[A][town][work[A][town][i]-BASE]+min_cost[B][town][work[B][town][k]-BASE];

				if(at2 == CALC.end() || tmp_cost < CALC[rev_start_time]){
					CALC[rev_start_time] = tmp_cost;
				}
			}
		}

		for(auto at3: CALC){
			return_start[town].push_back(Data(at3.first,at3.second));
		}
		sort(return_start[town].begin(),return_start[town].end());
	}

	//各町から、出発時刻別の、函館または東京への帰宅最短コストを求める
	int ans = BIG_NUM;
	int ret;

	for(int start_town = 0; start_town < node_index; start_town++){
		if(return_start[start_town].size() == 0)continue; //そもそも会えない街ならSKIP

		ret = rev_dijkstra(start_town);
		if(ret == BIG_NUM)continue; //函館または東京に戻れないならSKIP

		ans = min(ans,ret);
	}

	if(ans == BIG_NUM){
		printf("0\n");
	}else{
		printf("%d\n",ans);
	}
}

int main(){

	while(true){
		scanf("%d",&N);
		if(N == 0)break;

		func();
	}
	return 0;
}



Measured memory_bytes: 3592