#include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)

using namespace std;

struct Info {
  int fromStationID,toStationID;
  int fromTimeID,toTimeID;
  int cost;
};

const int IINF = INT_MAX;
const int MAX_STATION = 100;
const int MAX_EVENT   = 4000;
int   toDest[2][MAX_STATION][MAX_EVENT+10]; // toDest[0][][] <- hakodate, toDest[1][][] <- tokyo, toDest[][stationID][timeID] := ????????????stationID???timeID??????????????§?????°?????????????°?
int fromDest[2][MAX_STATION][MAX_EVENT+10]; // fromDest[0][][] <- hakodate, fromDest[1][][] <- tokyo, fromDest[][stationID][timeID] := ???????????§???stationID??????timeID??????????????????????????°????????????????????????????????????????°????

int stationIDIndex;
map<string,int> stationIDTable;
vector<int> T;

void init(){
  stationIDIndex = 0;
  stationIDTable.clear();
  T.clear();
}

inline int convertStringIntoTime(string s){
  return ( ( s[0] - '0' ) * 10 + ( s[1] - '0' ) ) * 60 + ( ( s[3] - '0' ) * 10 + ( s[4] - '0' ) ) ;
}

inline int calcTimeID(int _time) {
  return lower_bound(T.begin(),T.end(),_time) - T.begin();
}

Info convertStringIntoInfo(string context){
  vector<string> buf;
  stringstream ss;
  ss << context;
  while( ss >> context ){
    buf.push_back(context);
  }
  assert( buf.size() == 5 );
  int fromStationID = ( stationIDTable.count(buf[0]) ? stationIDTable[buf[0]] : ( stationIDTable[buf[0]] = stationIDIndex++ ) );
  int   toStationID = ( stationIDTable.count(buf[2]) ? stationIDTable[buf[2]] : ( stationIDTable[buf[2]] = stationIDIndex++ ) );
  int fromTime      = convertStringIntoTime(buf[1]);
  int   toTime      = convertStringIntoTime(buf[3]);
  if( fromTime < convertStringIntoTime("08:00") || toTime > convertStringIntoTime("18:00") ) {
    return (Info){-1,-1,-1,-1,-1};
  }
  T.push_back(fromTime);
  T.push_back(toTime);
  return (Info){fromStationID,toStationID,fromTime,toTime,(atoi)(buf[4].c_str())};
}

bool cmp_to(const Info &a,const Info &b) {
  if( a.toTimeID != b.toTimeID) a.toTimeID < b.toTimeID;
  return a.fromTimeID < b.fromTimeID;
}

bool cmp_from(const Info &a,const Info &b) {
  if( a.fromTimeID != b.fromTimeID ) a.fromTimeID > b.fromTimeID;
  return a.toTimeID > b.toTimeID;
}

void makeToDest(vector<Info> &vec,int hakodateID,int tokyoID,int startTimeID,int endTimeID) {
  assert( startTimeID == 0 );
  rep(i,2) rep(j,stationIDIndex) rep(k,endTimeID+1) toDest[i][j][k] = IINF;
  toDest[0][hakodateID][startTimeID] = toDest[1][tokyoID][startTimeID] = 0;
  sort(vec.begin(),vec.end(),cmp_to);
  int cur = 0;

  REP(timeID,startTimeID,endTimeID+1){
    if( timeID-1 >= startTimeID ) {
      rep(stationID,stationIDIndex){
	rep(j,2){
	  toDest[j][stationID][timeID] = min(toDest[j][stationID][timeID],
					     toDest[j][stationID][timeID-1]);
	}
      }
    }
    while( cur < (int)vec.size() && vec[cur].fromTimeID == timeID ){
      rep(j,2){
	if( toDest[j][vec[cur].fromStationID][timeID] == IINF ) continue;
	toDest[j][vec[cur].toStationID][vec[cur].toTimeID] = min(toDest[j][vec[cur].toStationID][vec[cur].toTimeID],
								 toDest[j][vec[cur].fromStationID][timeID]+vec[cur].cost);
      }
      ++cur;
    }
  }
}

void makeFromDest(vector<Info> &vec,int hakodateID,int tokyoID,int startTimeID,int endTimeID) {
  rep(i,2) rep(j,stationIDIndex) rep(k,endTimeID+1) fromDest[i][j][k] = IINF;
  fromDest[0][hakodateID][endTimeID] = fromDest[1][tokyoID][endTimeID] = 0;
  sort(vec.begin(),vec.end(),cmp_from);
  int cur = 0;
  for(int timeID=endTimeID;timeID>=startTimeID;timeID--){
    if( timeID+1 <= endTimeID ) {
      rep(stationID,stationIDIndex){
	rep(j,2){
	  fromDest[j][stationID][timeID] = min(fromDest[j][stationID][timeID],
					       fromDest[j][stationID][timeID+1]);
	}
      }
    }
    while( cur < (int)vec.size() && vec[cur].toTimeID == timeID ) {
      rep(j,2){
	if( fromDest[j][vec[cur].toStationID][timeID] == IINF ) continue;
	fromDest[j][vec[cur].fromStationID][vec[cur].fromTimeID] = min(fromDest[j][vec[cur].fromStationID][vec[cur].fromTimeID],
								       fromDest[j][vec[cur].toStationID][timeID]+vec[cur].cost);
      }
      ++cur;
    }
  }
}

void compute(vector<Info> &vec){

  if( !stationIDTable.count("Hakodate") || !stationIDTable.count("Tokyo") ) {
    puts("0");
    return;
  }

  int hakodateID   = stationIDTable["Hakodate"];
  int tokyoID      = stationIDTable["Tokyo"];
  int startTimeID  = calcTimeID(convertStringIntoTime("08:00")); 
  int   endTimeID  = calcTimeID(convertStringIntoTime("18:00")); 
  makeToDest(vec,hakodateID,tokyoID,startTimeID,endTimeID);
  makeFromDest(vec,hakodateID,tokyoID,startTimeID,endTimeID);

  int mini = IINF;
  rep(rendezvous,stationIDIndex){
    REP(timeID,startTimeID,endTimeID+1){
      if( toDest[0][rendezvous][timeID] == IINF || toDest[1][rendezvous][timeID] == IINF ) continue;
      int leaveTimeID = lower_bound(T.begin(),T.end(),T[timeID]+30) - T.begin();
      if( leaveTimeID >= (int)T.size() ) continue;
      if( fromDest[0][rendezvous][leaveTimeID] == IINF || fromDest[1][rendezvous][leaveTimeID] == IINF ) continue;
      mini = min(mini,
		 toDest[0][rendezvous][timeID]+toDest[1][rendezvous][timeID]+
		 fromDest[0][rendezvous][leaveTimeID]+fromDest[1][rendezvous][leaveTimeID]);
    }
  }  
  if( mini == IINF ) puts("0");
  else               cout << mini << endl;
}

int main(){
  int n;
  while( cin >> n, n ) {
    init();
    cin.ignore();
    vector<Info> vec;
    rep(i,n){
      string s;
      getline(cin,s);
      Info info = convertStringIntoInfo(s);
      if( info.fromStationID == -1 ) continue;
      vec.push_back(info);
    }
    T.push_back(convertStringIntoTime("08:00"));
    T.push_back(convertStringIntoTime("18:00"));
    sort(T.begin(),T.end());
    T.erase(unique(T.begin(),T.end()),T.end());
    rep(i,(int)vec.size()) {
      vec[i].fromTimeID = calcTimeID(vec[i].fromTimeID);
      vec[i].toTimeID   = calcTimeID(vec[i].toTimeID);
    }
    compute(vec);
  }
  return 0;
}