#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)     (C).begin(),(C).end()
#define pb         push_back
#define mp         make_pair

const int N = 100;
const int inf = (1 << 28);

class Edge{
public:
  int sh,sm,dh,dm;
  int d;
  int cost;
};

class state{
public:
  int now,h,m;
  int cost;
  bool operator<(const state & a)const{
    return cost > a.cost;
  }
};

bool isless(int h,int m,int nh,int nm){
  if (h < nh)return true;
  else if (h == nh && m <= nm)return true;
  return false;
}

bool isgreater(int h,int m,int nh,int nm){
  if (h > nh)return true;
  else if (h == nh && m >= nm)return true;
  return false;
}

void dijkstra(int n,int s,vector<Edge>*edge,int cost[24][60][N],
	      bool isrev){
  rep(i,24)rep(j,60)rep(k,n)cost[i][j][k]=inf;
  priority_queue<state> Q;
  if (isrev)Q.push((state){s,17,59,0});
  else Q.push((state){s,8,0,0});

  while(!Q.empty()){
    state now = Q.top();Q.pop();
    if (cost[now.h][now.m][now.now] != inf)continue;
    cost[now.h][now.m][now.now]=now.cost;
    rep(i,edge[now.now].size()){
      if (isrev){
	if (isgreater(now.h,now.m,edge[now.now][i].sh,edge[now.now][i].sm))
	  Q.push((state){edge[now.now][i].d,edge[now.now][i].dh,
			   edge[now.now][i].dm,
			   now.cost+edge[now.now][i].cost});
      }else {
	if (isless(now.h,now.m,edge[now.now][i].sh,edge[now.now][i].sm))
	  Q.push((state){edge[now.now][i].d,edge[now.now][i].dh,
			   edge[now.now][i].dm,
			   now.cost+edge[now.now][i].cost});
      }
    }
  }


  if (isrev){
    rep(k,100){
      int tmp = inf;
      for(int i=17;i>=6;i--){
	for(int j=59;j>=0;j--){
	  cost[i][j][k]=min(cost[i][j][k],tmp);
	  tmp=min(cost[i][j][k],tmp);
	}
      }
    }
  }else {
    rep(k,100){
      int tmp = inf;
      rep(i,24){
	rep(j,60){
	  cost[i][j][k]=min(cost[i][j][k],tmp);
	  tmp=min(tmp,cost[i][j][k]);
	}
      }
    }
  }
}

//from tokyo,from hakodate, to tokyo,to hakodate
int ft[24][60][N],fh[24][60][N],tt[24][60][N],th[24][60][N];
int solve(int n,int hakodate,int tokyo,vector<Edge>*edge,
	  vector<Edge>*revedge){


  dijkstra(n,tokyo,edge,ft,false);
  dijkstra(n,hakodate,edge,fh,false);
  dijkstra(n,tokyo,revedge,tt,true);
  dijkstra(n,hakodate,revedge,th,true);

  
  int ret = inf;
  rep(k,n){
    int tmp = inf;
    REP(i,8,18){
      rep(j,30){
	tmp=min(tmp,ft[i][j][k]+fh[i][j][k]+tt[i][j+30][k]+th[i][j+30][k]);
      }
      REP(j,30,60){
	tmp=min(tmp,ft[i][j][k]+fh[i][j][k]+tt[i+1][(j+30)%60][k]+th[i+1][(j+30)%60][k]);
      }
    }
    ret=min(ret,tmp);
  }
  return ret;
}


int getnum(string &a,map<string,int> & M){
  int index=M.size();
  if (M.find(a) == M.end())M[a]=index;
  return M[a];
}

main(){
  int n;
  vector<Edge> edge[N];
  vector<Edge> rev[N];
  const string name[2]={"Hakodate","Tokyo"};
  while(cin>>n && n){
    rep(i,N)edge[i].clear(),rev[i].clear();
    map<string,int> M;

    string from,to;
    int f,t;
    int sh,sm,dh,dm;
    int cost;
    char dummy;
    rep(i,n){
      cin>>from>>sh>>dummy>>sm;
      cin>>to>>dh>>dummy>>dm;
      cin>>cost;
      f=getnum(from,M);
      t=getnum(to,M);
      edge[f].pb((Edge){sh,sm,dh,dm,t,cost});
      rev[t].pb((Edge){dh,dm,sh,sm,f,cost});
    }

    
    int ans = solve(M.size(),M[name[0]],M[name[1]],edge,rev);
    if (ans == inf)cout <<0<<endl;
    else cout << ans << endl;

  }
}

Measured memory_bytes: 3392