Problem:
Problem F:
Young, Poor and Busy
Ken and Keiko are young, poor and busy. Short explanation: they are students, and ridden with part-time jobs. To make things worse, Ken lives in Hakodate and Keiko in Tokyo. They want to meet, but since they have neither time nor money, they have to go back to their respective jobs immediately after, and must be careful about transportation costs. Help them find the most economical meeting point.
Ken starts from Hakodate, Keiko from Tokyo. They know schedules and fares for all trains, and can choose to meet anywhere including their hometowns, but they cannot leave before 8am and must be back by 6pm in their respective towns. Train changes take no time (one can leave the same minute he/she arrives), but they want to meet for at least 30 minutes in the same city.
There can be up to 100 cities and 2000 direct connections, so you should devise an algorithm clever enough for the task.
Input
The input is a sequence of data sets.
The first line of a data set contains a single integer, the number of connections in the timetable. It is not greater than 2000.
Connections are given one on a line, in the following format.
Start_city HH
:
MM Arrival_city HH
:
MM price
Start_city
and
Arrival_city
are composed of up to 16 alphabetical characters, with only the first one in upper case. Departure and arrival times are given in hours and minutes (two digits each, separated by ":") from 00:00 to 23:59. Arrival time is strictly after departure time. The
price
for one connection is an integer between 1 and 10000, inclusive. Fields are separated by spaces.
The end of the input is marked by a line containing a zero.
Output
The output should contain one integer for each data set, the lowest cost possible. This is the total fare of all connections they use.
If there is no solution to a data set, you should output a zero.
The solution to each data set should be given in a separate line.
Sample Input
5
Hakodate 08:15 Morioka 12:30 2500
Morioka 14:05 Hakodate 17:30 2500
Morioka 15:30 Hakodate 18:00 3000
Morioka 14:30 Tokyo 17:50 3000
Tokyo 08:30 Morioka 13:35 3000
4
Hakodate 08:15 Morioka 12:30 2500
Morioka 14:04 Hakodate 17:30 2500
Morioka 14:30 Tokyo 17:50 3000
Tokyo 08:30 Morioka 13:35 3000
18
Hakodate 09:55 Akita 10:53 3840
Hakodate 14:14 Akita 16:09 1920
Hakodate 18:36 Akita 19:33 3840
Hakodate 08:00 Morioka 08:53 3550
Hakodate 22:40 Morioka 23:34 3550
Akita 14:23 Tokyo 14:53 2010
Akita 20:36 Tokyo 21:06 2010
Akita 08:20 Hakodate 09:18 3840
Akita 13:56 Hakodate 14:54 3840
Akita 21:37 Hakodate 22:35 3840
Morioka 09:51 Tokyo 10:31 2660
Morioka 14:49 Tokyo 15:29 2660
Morioka 19:42 Tokyo 20:22 2660
Morioka 15:11 Hakodate 16:04 3550
Morioka 23:03 Hakodate 23:56 3550
Tokyo 09:44 Morioka 11:04 1330
Tokyo 21:54 Morioka 22:34 2660
Tokyo 11:34 Akita 12:04 2010
0
Output for the Sample Input
11000
0
11090

Submitted solutions:

code_snippet: #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;
}
accuracy: 1
time_ms: 30
memory_kb: 3592
final_rank: 4

code_snippet: #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;
}
accuracy: 1
time_ms: 10
memory_kb: 5740
final_rank: 6

code_snippet: #include<string>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
using namespace std;
char in[20];
vector<pair<pair<int,int>,int> >g[110][1440];
vector<pair<pair<int,int>,int> >g2[110][1440];
int ijk[110][1440];
int v[110][1440];
int s[4][110][1440];
int main(){
	int a;
	while(scanf("%d",&a),a){
		for(int i=0;i<110;i++)for(int j=0;j<1440;j++){
			g[i][j].clear();
			g2[i][j].clear();
		}
		map<string,int>m;
		m["Hakodate"]=0;
		m["Tokyo"]=1;
		int n=2;
		for(int i=0;i<a;i++){
			scanf("%s",in);
			string na=in;
			if(!m.count(na))m[na]=n++;
			int p=m[na];
			int H,M;
			scanf("%d:%d",&H,&M);
			int t1=H*60+M;
			scanf("%s",in);
			string nb=in;
			if(!m.count(nb))m[nb]=n++;
			int q=m[nb];
			scanf("%d:%d",&H,&M);
			int t2=H*60+M;
			int r;
			scanf("%d",&r);
			g[p][t1].push_back(make_pair(make_pair(q,t2),r));
			g2[q][t2].push_back(make_pair(make_pair(p,t1),r));
		}
		for(int i=0;i<110;i++)for(int j=0;j<1440;j++){
			v[i][j]=0;ijk[i][j]=99999999;
		}
		priority_queue<pair<int,pair<int,int> > > Q;
		Q.push(make_pair(0,make_pair(0,480)));
		ijk[0][480]=0;
		while(Q.size()){
			int cost=-Q.top().first;
			int at=Q.top().second.first;
			int t=Q.top().second.second;
			Q.pop();
			if(v[at][t])continue;
			v[at][t]=1;
			if(t<1080&&!v[at][t+1]&&ijk[at][t+1]>cost){
				ijk[at][t+1]=cost;
				Q.push(make_pair(-cost,make_pair(at,t+1)));
			}
			for(int i=0;i<g[at][t].size();i++){
				int x=g[at][t][i].first.first;
				int y=g[at][t][i].first.second;
				int z=g[at][t][i].second;
				if(!v[x][y]&&ijk[x][y]>cost+z){
					ijk[x][y]=cost+z;
					Q.push(make_pair(-cost-z,make_pair(x,y)));
				}
			}
		}
		for(int i=0;i<n;i++)for(int j=0;j<1440;j++)
			s[0][i][j]=ijk[i][j];
		for(int i=0;i<110;i++)for(int j=0;j<1440;j++){
			v[i][j]=0;ijk[i][j]=99999999;
		}
		Q.push(make_pair(0,make_pair(1,480)));
		ijk[1][480]=0;
		while(Q.size()){
			int cost=-Q.top().first;
			int at=Q.top().second.first;
			int t=Q.top().second.second;
			Q.pop();
			if(v[at][t])continue;
			v[at][t]=1;
			if(t<1080&&!v[at][t+1]&&ijk[at][t+1]>cost){
				ijk[at][t+1]=cost;
				Q.push(make_pair(-cost,make_pair(at,t+1)));
			}
			for(int i=0;i<g[at][t].size();i++){
				int x=g[at][t][i].first.first;
				int y=g[at][t][i].first.second;
				int z=g[at][t][i].second;
				if(!v[x][y]&&ijk[x][y]>cost+z){
					ijk[x][y]=cost+z;
					Q.push(make_pair(-cost-z,make_pair(x,y)));
				}
			}
		}
		for(int i=0;i<n;i++)for(int j=0;j<1440;j++)
			s[1][i][j]=ijk[i][j];
		for(int i=0;i<110;i++)for(int j=0;j<1440;j++){
			v[i][j]=0;ijk[i][j]=99999999;
		}
		Q.push(make_pair(0,make_pair(0,1080)));
		ijk[0][1080]=0;
		while(Q.size()){
			int cost=-Q.top().first;
			int at=Q.top().second.first;
			int t=Q.top().second.second;
			Q.pop();
			if(v[at][t])continue;
			v[at][t]=1;
			if(t>480&&!v[at][t-1]&&ijk[at][t-1]>cost){
				ijk[at][t-1]=cost;
				Q.push(make_pair(-cost,make_pair(at,t-1)));
			}
			for(int i=0;i<g2[at][t].size();i++){
				int x=g2[at][t][i].first.first;
				int y=g2[at][t][i].first.second;
				int z=g2[at][t][i].second;
				if(!v[x][y]&&ijk[x][y]>cost+z){
					ijk[x][y]=cost+z;
					Q.push(make_pair(-cost-z,make_pair(x,y)));
				}
			}
		}
		for(int i=0;i<n;i++)for(int j=0;j<1440;j++)
			s[2][i][j]=ijk[i][j];
		for(int i=0;i<110;i++)for(int j=0;j<1440;j++){
			v[i][j]=0;ijk[i][j]=99999999;
		}
		Q.push(make_pair(0,make_pair(1,1080)));
		ijk[1][1080]=0;
		while(Q.size()){
			int cost=-Q.top().first;
			int at=Q.top().second.first;
			int t=Q.top().second.second;
			Q.pop();
			if(v[at][t])continue;
			v[at][t]=1;
			if(t>480&&!v[at][t-1]&&ijk[at][t-1]>cost){
				ijk[at][t-1]=cost;
				Q.push(make_pair(-cost,make_pair(at,t-1)));
			}
			for(int i=0;i<g2[at][t].size();i++){
				int x=g2[at][t][i].first.first;
				int y=g2[at][t][i].first.second;
				int z=g2[at][t][i].second;
				if(!v[x][y]&&ijk[x][y]>cost+z){
					ijk[x][y]=cost+z;
					Q.push(make_pair(-cost-z,make_pair(x,y)));
				}
			}
		}
		for(int i=0;i<n;i++)for(int j=0;j<1440;j++)
			s[3][i][j]=ijk[i][j];
		int ret=999999999;
		for(int i=0;i<n;i++){
			for(int j=480;j<=1410;j++){
				ret=min(ret,s[0][i][j]+s[1][i][j]+s[2][i][j+30]+s[3][i][j+30]);
			}
		}
		if(ret>99999999)printf("0\n");
		else printf("%d\n",ret);
	}
}
accuracy: 1
time_ms: 10
memory_kb: 10864
final_rank: 8

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <numeric>
#include <cctype>
#include <tuple>
#include <iterator>
#include <bitset>
#include <random>
#include <assert.h>
#include <unordered_map>

#ifdef _MSC_VER
#include <agents.h>
#endif

#define FOR(i, a, b) for(int i = (a); i < (int)(b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define ALL(v) v.begin(), v.end()
#define REV(v) v.rbegin(), v.rend()
#define MEMSET(v, s) memset(v, s, sizeof(v))
#define X first
#define Y second
#define MP make_pair
#define umap unordered_map

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> P;

const int N = 110;
const int T = 610;

int cost[4][N*T];

inline int f(int n, int t){
	return n*T + t;
}

vector<P> G[N*T], rev[N*T];
vector<int> v[N];

void dijk(int start, int t, int *opt, vector<P> *graph){
	opt[f(start, t)] = 0;
	priority_queue<P, vector<P>, greater<P>> q;
	q.push(MP(0, f(start, t)));

	while (!q.empty()){
		int d = q.top().first;
		int pos = q.top().second;

		q.pop();

		if (opt[pos] < d) continue;

		for (auto &e : graph[pos]){
			if (opt[e.first] <= d + e.second)continue;
			opt[e.first] = d + e.second;
			q.push(MP(d + e.second, e.first));
		}
	}
}

void pp(int i, int pos, int t){
	cout << (i % 2 ? "to" : "from") << " " << (i / 2 ? "Hakodate" : "Tokyo") << endl;
	cout << cost[i][f(pos, t)] << endl;
}

int main(){
	int n;
	while (cin >> n, n){
		rep(i, N*T) G[i].clear();
		rep(i, N*T) rev[i].clear();
		rep(i, N) v[i].clear(), v[i].push_back(0), v[i].push_back(600);

		map<string, int> m;
		int idx = 0;
		m["Tokyo"] = idx++;
		m["Hakodate"] = idx++;
		rep(i, n){
			string s, t;
			int h1, m1, h2, m2, cost;
			char c;
			cin >> s >> h1 >> c >> m1 >> t >> h2 >> c >> m2 >> cost;
			int t1 = h1 * 60 + m1 - 480, t2 = h2 * 60 + m2 - 480;
			if (0 <= t1 && t1 <= 600 && 0 <= t2 && t2 <= 600){
				if (!m.count(s)) m[s] = idx++;
				if (!m.count(t)) m[t] = idx++;
				int from = f(m[s], t1), to = f(m[t], t2);
				G[from].push_back(MP(to, cost));
				rev[to].push_back(MP(from, cost));
				v[m[s]].push_back(t1);
				v[m[t]].push_back(t2);
			}
		}

		rep(i, idx){
			sort(ALL(v[i]));
			v[i].erase(unique(ALL(v[i])), v[i].end());
			rep(j, v[i].size()){
				if (j + 1 < v[i].size()) G[f(i, v[i][j])].push_back(MP(f(i, v[i][j + 1]), 0));
				if (j - 1 >= 0) rev[f(i, v[i][j])].push_back(MP(f(i, v[i][j - 1]), 0));
			}
		}

		rep(i, 4){
			MEMSET(cost[i], 0x7f);
			// Tokyo -> x, x -> Tokyo, Hakodate -> x, x -> Hakodate
			dijk(i / 2, i % 2 ? 600 : 0, cost[i], i % 2 ? rev : G);
		}

		rep(k, 2) rep(i, idx){
			for (int j = 0+1; j <= 600; ++j){
				cost[k * 2][f(i, j)] = min(cost[k * 2][f(i, j)], cost[k * 2][f(i, j - 1)]);
			}
			for (int j = 600-1; j >= 0; --j){
				cost[k * 2 + 1][f(i, j)] = min(cost[k * 2 + 1][f(i, j)], cost[k * 2 + 1][f(i, j + 1)]);
			}
		}

		int ans = 1e9;
		rep(i, idx) for (int j = 0; j <= 600 - 30; ++j){
			//pp(0, i, j);
			//pp(1, i, j+30);
			//pp(2, i, j);
			//pp(3, i, j+30);
			int a = f(i, j), b = f(i, j + 30);
			if ((cost[0][a] | cost[1][b] | cost[2][a] | cost[3][b]) >= ans) continue;
			ans = min(ans, cost[0][a] + cost[1][b] + cost[2][a] + cost[3][b]);
		}
		cout << (ans < 1e9 ? ans : 0) << endl;
	}



	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 5608
final_rank: 5

code_snippet: #include<iostream>
#include<queue>
#include<string>
#include<map>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<set>
#include<cstdio>
#include<cassert>

using namespace std;

#define foreach(i,o) for(__typeof((o).begin()) i = (o).begin(); i != (o).end(); ++i)

const int max_place = 101;
const int max_time = 601;
const int MAX_V = 2010;
const int inf = 1<<28;

struct edge{
  int src, dst;
  int cost;
  edge(int src, int dst, int cost):src(src), dst(dst), cost(cost){}
};

struct state{
  int pos;
  int prev;
  int cost;
  
  state(int pos, int prev, int cost):pos(pos),prev(prev),cost(cost){}

  bool operator>(const state &t)const{
    if(cost!=t.cost)return cost>t.cost;
    if(prev!=t.prev)return prev>t.prev;
    if(pos!=t.pos)return pos>t.pos;
    return false;
  }
};

typedef vector<edge> edges;
typedef vector<edges> graph;

int convTime(const string &s){
  int h = atoi(s.substr(0,2).c_str());
  int m = atoi(s.substr(3,2).c_str());
  return 60 * h + m;
}

string revTime(int t){
  char buf[32];
  sprintf(buf, "%02d:%02d", t/60, t%60);
  return string(buf);
}

int **dist = NULL;
void johnson(const graph &tmp_g){
  graph g = tmp_g;
  const int v = g.size();
  
  for(int i = 0; i < v; ++i){
    dist[i] = new int[v];
    for(int j = 0; j < v; ++j){
      dist[i][j] = inf;
    }
    dist[i][i] = 0;
  }

  for(int s = 0; s < v; ++s){
    priority_queue<state, vector<state>, greater<state> > q;
    q.push(state(s,s,0));
    while(!q.empty()){
      state cur = q.top(); q.pop();
      for(int i = 0; i < (int)g[cur.pos].size(); ++i){
        edge e = g[cur.pos][i];
        int cost = cur.cost + e.cost;
        assert(cost>=0);
        if(dist[s][e.dst] > cost){
          dist[s][e.dst] = cost;
          q.push(state(e.dst,cur.pos,cost));
        }
      }
    }
  }
  
  return ;  
}

int main()
{
  int n;
  while(cin>>n && n){
    int id = 1;
    int vid = 0;
    map<string,int> cityDict;
    map<int,string> revCityDict;
    set<int> cityEvTimes[max_place];
    graph g(MAX_V);
    
    map<pair<int,int>, int> vID;
    map<int,pair<int,int> > revID;
    
    for(int i = 0; i < n; ++i){
      string from, ftime, to, ttime;
      int cost;

      cin >> from >> ftime >> to >> ttime >> cost;
      if(!cityDict.count(from)){
        cityDict[from] = id;
        revCityDict[id] = from;
        ++id;
      }
      if(!cityDict.count(to)){
        cityDict[to] = id;
        revCityDict[id] = to;
        ++id;
      }

      int src = cityDict[from];
      int dst = cityDict[to];
      int srcTime = convTime(ftime) - 480;
      int dstTime = convTime(ttime) - 480;
      
      if( dstTime >= 0 && dstTime < max_time && srcTime >= 0 && srcTime < max_time ){
        if( !vID.count(make_pair(src,srcTime)) ){
          vID[make_pair(src,srcTime)] = vid;
          revID[vid] = make_pair(src,srcTime);
          ++vid;
        }
        cityEvTimes[src].insert(srcTime);
        if( !vID.count(make_pair(dst,dstTime)) ){
          vID[make_pair(dst,dstTime)] = vid;
          revID[vid] = make_pair(dst,dstTime);
          ++vid;
        }
        cityEvTimes[dst].insert(dstTime);
        
        g[vID[make_pair(src,srcTime)]].push_back( edge(vID[make_pair(src,srcTime)], vID[make_pair(dst,dstTime)], cost) );
      }

    }
    g.resize(vID.size());
    
    for(int i = 1; i < id; ++i){
      foreach(it2, cityEvTimes[i]){
        set<int>::iterator it3 = it2;
        ++it3;
        if( it3 != cityEvTimes[i].end() ){
          g[vID[make_pair(i,*it2)]].push_back( edge(vID[make_pair(i,*it2)], vID[make_pair(i,*it3)], 0) );
        }
      }
    }
    
    dist=new int*[g.size()];
    for(int i = 0; i < (int)g.size(); ++i){
      dist[i] = new int[g.size()];
    }
    
    johnson(g);

    int res = inf;
    int kenInitial = cityDict["Tokyo"];
    int keikoInitial = cityDict["Hakodate"];

    int ken_st, keiko_st;
    if( cityEvTimes[kenInitial].size() > 0 && cityEvTimes[keikoInitial].size() > 0 ){
      ken_st = vID[make_pair(kenInitial, *(cityEvTimes[kenInitial].begin()))];
      keiko_st = vID[make_pair(keikoInitial, *(cityEvTimes[keikoInitial].begin()))];

      for(int i = 1; i < id; ++i){
        foreach(ev1, cityEvTimes[i]){
          int v1 = vID[make_pair(i,*ev1)];
          foreach(ev2, cityEvTimes[i]){
            int v2 = vID[make_pair(i,*ev2)];
            int st = max(*ev1, *ev2) + 30;
            int from = -1;

            if(cityEvTimes[i].lower_bound(st)!=cityEvTimes[i].end()){
              from = vID[make_pair(i,*(cityEvTimes[i].lower_bound(st)))];
            }
            if(from<0)continue;
            foreach(ev3, cityEvTimes[kenInitial]){
              if( *ev3 < st ) continue;
              int v3 = vID[make_pair(kenInitial,*ev3)];
              foreach(ev4, cityEvTimes[keikoInitial]){
                if( *ev4 < st ) continue;
                int v4 = vID[make_pair(keikoInitial, *ev4)];
                res = min(res, dist[ken_st][v1] + dist[keiko_st][v2] + dist[from][v3] + dist[from][v4]);
              }
            }
          }
        }
      }
    }
 

    if(res>=inf)res = 0;
    cout << res << endl;

    for(int i = 0; i < (int)g.size(); ++i){
      delete [] dist[i];
    }
    delete [] dist;
    
  }
  return 0;
}
accuracy: 1
time_ms: 1550
memory_kb: 23180
final_rank: 10

code_snippet: #include<iostream>
#include<queue>
#include<string>
#include<map>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<set>
#include<cstdio>
#include<cassert>

using namespace std;

#define foreach(i,o) for(__typeof((o).begin()) i = (o).begin(); i != (o).end(); ++i)

const int max_place = 101;
const int max_time = 601;
const int MAX_V = 2010;
const int inf = 1<<28;

struct edge{
  int src, dst;
  int cost;
  edge(int src, int dst, int cost):src(src), dst(dst), cost(cost){}
};

struct state{
  int pos;
  int prev;
  int cost;
  
  state(int pos, int prev, int cost):pos(pos),prev(prev),cost(cost){}

  bool operator>(const state &t)const{
    if(cost!=t.cost)return cost>t.cost;
    if(prev!=t.prev)return prev>t.prev;
    if(pos!=t.pos)return pos>t.pos;
    return false;
  }
};

typedef vector<edge> edges;
typedef vector<edges> graph;

int convTime(const string &s){
  int h = atoi(s.substr(0,2).c_str());
  int m = atoi(s.substr(3,2).c_str());
  return 60 * h + m;
}

string revTime(int t){
  char buf[32];
  sprintf(buf, "%02d:%02d", t/60, t%60);
  return string(buf);
}

// static int dist[MAX_V][MAX_V];
int **dist = NULL;
//  = new int* [v];
void johnson(const graph &tmp_g){
  graph g = tmp_g;
  
  const int v = g.size();
  // [v];
  // int **prev = new static int prev[MAX_V][MAX_V];
  
  for(int i = 0; i < v; ++i){
    dist[i] = new int[v];
    for(int j = 0; j < v; ++j){
      dist[i][j] = inf;
      // prev[i][j] = -1;
    }
    dist[i][i] = 0;
  }

  for(int s = 0; s < v; ++s){
    priority_queue<state, vector<state>, greater<state> > q;
    q.push(state(s,s,0));
    // bool vis[v]
    while(!q.empty()){
      state cur = q.top(); q.pop();
      // if(prev[s][cur.pos]!=-1)continue;
      // prev[s][cur.pos] = cur.prev;
      for(int i = 0; i < (int)g[cur.pos].size(); ++i){
        edge e = g[cur.pos][i];
        int cost = cur.cost + e.cost;
        assert(cost>=0);
        if(dist[s][e.dst] > cost){
          dist[s][e.dst] = cost;
          q.push(state(e.dst,cur.pos,cost));
        }
      }
    }
  }
  
  return ;  
}

int main()
{
  int n;
  while(cin>>n && n){
    int id = 1;
    int vid = 0;
    map<string,int> cityDict;
    map<int,string> revCityDict;
    set<int> cityEvTimes[max_place];
    graph g(MAX_V);
    
    map<pair<int,int>, int> vID;
    map<int,pair<int,int> > revID;
    
    for(int i = 0; i < n; ++i){
      string from, ftime, to, ttime;
      int cost;

      cin >> from >> ftime >> to >> ttime >> cost;
      if(!cityDict.count(from)){
        cityDict[from] = id;
        revCityDict[id] = from;
        ++id;
      }
      if(!cityDict.count(to)){
        cityDict[to] = id;
        revCityDict[id] = to;
        ++id;
      }

      int src = cityDict[from];
      int dst = cityDict[to];
      int srcTime = convTime(ftime) - 480;
      int dstTime = convTime(ttime) - 480;
      
      if( dstTime >= 0 && dstTime < max_time && srcTime >= 0 && srcTime < max_time ){
        if( !vID.count(make_pair(src,srcTime)) ){
          vID[make_pair(src,srcTime)] = vid;
          revID[vid] = make_pair(src,srcTime);
          ++vid;
        }
        cityEvTimes[src].insert(srcTime);
        if( !vID.count(make_pair(dst,dstTime)) ){
          vID[make_pair(dst,dstTime)] = vid;
          revID[vid] = make_pair(dst,dstTime);
          ++vid;
        }
        cityEvTimes[dst].insert(dstTime);
        
        g[vID[make_pair(src,srcTime)]].push_back( edge(vID[make_pair(src,srcTime)], vID[make_pair(dst,dstTime)], cost) );
      }

    }
    g.resize(vID.size());
    
    for(int i = 1; i < id; ++i){
      foreach(it2, cityEvTimes[i]){
        set<int>::iterator it3 = it2;
        ++it3;
        if( it3 != cityEvTimes[i].end() ){
          g[vID[make_pair(i,*it2)]].push_back( edge(vID[make_pair(i,*it2)], vID[make_pair(i,*it3)], 0) );
        }
      }
    }
    
    dist=new int*[g.size()];
    for(int i = 0; i < (int)g.size(); ++i){
      dist[i] = new int[g.size()];
    }
    
    johnson(g);

    int res = inf;
    int kenInitial = cityDict["Tokyo"];
    int keikoInitial = cityDict["Hakodate"];

    int ken_st, keiko_st;
    if( cityEvTimes[kenInitial].size() > 0 && cityEvTimes[keikoInitial].size() > 0 ){
      ken_st = vID[make_pair(kenInitial, *(cityEvTimes[kenInitial].begin()))];
      keiko_st = vID[make_pair(keikoInitial, *(cityEvTimes[keikoInitial].begin()))];

      for(int i = 1; i < id; ++i){
        foreach(ev1, cityEvTimes[i]){
          int v1 = vID[make_pair(i,*ev1)];
          foreach(ev2, cityEvTimes[i]){
            int v2 = vID[make_pair(i,*ev2)];
            int st = max(*ev1, *ev2) + 30;
            int from = -1;

            if(cityEvTimes[i].lower_bound(st)!=cityEvTimes[i].end()){
              from = vID[make_pair(i,*(cityEvTimes[i].lower_bound(st)))];
            }
            if(from<0)continue;
            foreach(ev3, cityEvTimes[kenInitial]){
              if( *ev3 < st ) continue;
              int v3 = vID[make_pair(kenInitial,*ev3)];
              foreach(ev4, cityEvTimes[keikoInitial]){
                if( *ev4 < st ) continue;
                int v4 = vID[make_pair(keikoInitial, *ev4)];
                res = min(res, dist[ken_st][v1] + dist[keiko_st][v2] + dist[from][v3] + dist[from][v4]);
              }
            }
          }
        }
      }
      
    }
 

    if(res>=inf)res = 0;
    cout << res << endl;

    for(int i = 0; i < (int)g.size(); ++i){
      delete [] dist[i];
    }
    delete [] dist;
    
  }
  return 0;
}
accuracy: 1
time_ms: 1540
memory_kb: 23184
final_rank: 9

code_snippet: #include<iostream>
#include<queue>
#include<string>
#include<map>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<set>
#include<cstdio>
#include<cassert>

using namespace std;

#define foreach(i,o) for(__typeof((o).begin()) i = (o).begin(); i != (o).end(); ++i)

const int max_place = 101;
const int max_time = 601;
const int MAX_V = 2010;
const int inf = 1<<28;

struct edge{
  int src, dst;
  int cost;
  edge(int src, int dst, int cost):src(src), dst(dst), cost(cost){}
};

struct state{
  int pos;
  int prev;
  int cost;
  
  state(int pos, int prev, int cost):pos(pos),prev(prev),cost(cost){}

  bool operator>(const state &t)const{
    if(cost!=t.cost)return cost>t.cost;
    if(prev!=t.prev)return prev>t.prev;
    if(pos!=t.pos)return pos>t.pos;
    return false;
  }
};

typedef vector<edge> edges;
typedef vector<edges> graph;

int convTime(const string &s){
  int h = atoi(s.substr(0,2).c_str());
  int m = atoi(s.substr(3,2).c_str());
  return 60 * h + m;
}

string revTime(int t){
  char buf[32];
  sprintf(buf, "%02d:%02d", t/60, t%60);
  return string(buf);
}

static int dist[MAX_V][MAX_V];
void johnson(const graph &tmp_g){
  graph g = tmp_g;
  
  const int v = g.size();
  //static int h[MAX_V];
  static int prev[MAX_V][MAX_V];
  

  /*
 for(int i = 0; i < v; ++i){
    h[i] = 0;
  }
  */

  /*
  for(int i = 0; i <= v; ++i){
    bool end = true;
    for(int j = 0; j < v; ++j){
      for(int k = 0; k < (int)g[j].size(); ++k){
        edge e = g[j][k];
        int tmp = h[j] + e.cost;
        if( h[e.dst] > tmp ){
          h[e.dst] = tmp;
          end = false;
        }
      }
    }
    if(end)break;
    // do not detect an negative cycle.
  }
  */

  for(int i = 0; i < v; ++i){
    for(int j = 0; j < v; ++j){
      dist[i][j] = inf;
      prev[i][j] = -1;
    }
    dist[i][i] = 0;
  }

  /*
  for(int i = 0; i < v; ++i){
    for(int j = 0; j < (int)g[i].size(); ++j){
      g[i][j].cost += h[i] - h[g[i][j].dst];
    }
  }
  */

  for(int s = 0; s < v; ++s){
    priority_queue<state, vector<state>, greater<state> > q;
    q.push(state(s,s,0));
    while(!q.empty()){
      state cur = q.top(); q.pop();
      if(prev[s][cur.pos]!=-1)continue;
      prev[s][cur.pos] = cur.prev;
      for(int i = 0; i < (int)g[cur.pos].size(); ++i){
        edge e = g[cur.pos][i];
        int cost = cur.cost + e.cost;
        assert(cost>=0);
        if(dist[s][e.dst] > cost){
          dist[s][e.dst] = cost;
          q.push(state(e.dst,cur.pos,cost));
        }
      }
    }
    //    for(int i = 0; i < v; ++i){
      //dist[s][i] += h[i] - h[s];
    //}
  }

  return ;  
}

int main()
{
  int n;
  while(cin>>n && n){
    int id = 1;
    int vid = 0;
    map<string,int> cityDict;
    map<int,string> revCityDict;
    set<int> cityEvTimes[max_place];
    graph g(MAX_V);
    
    map<pair<int,int>, int> vID;
    map<int,pair<int,int> > revID;
    
    for(int i = 0; i < n; ++i){
      string from, ftime, to, ttime;
      int cost;

      cin >> from >> ftime >> to >> ttime >> cost;
      if(!cityDict.count(from)){
        cityDict[from] = id;
        revCityDict[id] = from;
        ++id;
      }
      if(!cityDict.count(to)){
        cityDict[to] = id;
        revCityDict[id] = to;
        ++id;
      }

      int src = cityDict[from];
      int dst = cityDict[to];
      int srcTime = convTime(ftime) - 480;
      int dstTime = convTime(ttime) - 480;
      
      if( dstTime >= 0 && dstTime < max_time && srcTime >= 0 && srcTime < max_time ){
        if( !vID.count(make_pair(src,srcTime)) ){
          vID[make_pair(src,srcTime)] = vid;
          revID[vid] = make_pair(src,srcTime);
          ++vid;
        }
        cityEvTimes[src].insert(srcTime);
        if( !vID.count(make_pair(dst,dstTime)) ){
          vID[make_pair(dst,dstTime)] = vid;
          revID[vid] = make_pair(dst,dstTime);
          ++vid;
        }
        cityEvTimes[dst].insert(dstTime);
        
        g[vID[make_pair(src,srcTime)]].push_back( edge(vID[make_pair(src,srcTime)], vID[make_pair(dst,dstTime)], cost) );
      }

    }
    g.resize(vID.size());
    
    for(int i = 1; i < id; ++i){
      foreach(it2, cityEvTimes[i]){
        set<int>::iterator it3 = it2;
        ++it3;
        if( it3 != cityEvTimes[i].end() ){
          g[vID[make_pair(i,*it2)]].push_back( edge(vID[make_pair(i,*it2)], vID[make_pair(i,*it3)], 0) );
        }
      }
    }
    
    johnson(g);

    int res = inf;
    int kenInitial = cityDict["Tokyo"];
    int keikoInitial = cityDict["Hakodate"];

    int ken_st, keiko_st;
    if( cityEvTimes[kenInitial].size() > 0 && cityEvTimes[keikoInitial].size() > 0 ){
      ken_st = vID[make_pair(kenInitial, *(cityEvTimes[kenInitial].begin()))];
      keiko_st = vID[make_pair(keikoInitial, *(cityEvTimes[keikoInitial].begin()))];

      for(int i = 1; i < id; ++i){
        foreach(ev1, cityEvTimes[i]){
          int v1 = vID[make_pair(i,*ev1)];
          foreach(ev2, cityEvTimes[i]){
            int v2 = vID[make_pair(i,*ev2)];
            int st = max(*ev1, *ev2) + 30;
            int from = -1;

            if(cityEvTimes[i].lower_bound(st)!=cityEvTimes[i].end()){
              from = vID[make_pair(i,*(cityEvTimes[i].lower_bound(st)))];
            }
            if(from<0)continue;
            foreach(ev3, cityEvTimes[kenInitial]){
              if( *ev3 < st ) continue;
              int v3 = vID[make_pair(kenInitial,*ev3)];
              foreach(ev4, cityEvTimes[keikoInitial]){
                if( *ev4 < st ) continue;
                int v4 = vID[make_pair(keikoInitial, *ev4)];
                res = min(res, dist[ken_st][v1] + dist[keiko_st][v2] + dist[from][v3] + dist[from][v4]);
              }
            }
          }
        }
      }
      
    }
 

    if(res>=inf)res = 0;
    cout << res << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 1670
memory_kb: 32480
final_rank: 13

code_snippet: #include<iostream>
#include<queue>
#include<string>
#include<map>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<set>
#include<cstdio>
#include<cassert>

using namespace std;

#define foreach(i,o) for(__typeof((o).begin()) i = (o).begin(); i != (o).end(); ++i)

const int max_place = 101;
const int max_time = 601;
const int MAX_V = 2010;
const int inf = 1<<28;

struct edge{
  int src, dst;
  int cost;
  edge(int src, int dst, int cost):src(src), dst(dst), cost(cost){}
};

struct state{
  int pos;
  int prev;
  int cost;
  
  state(int pos, int prev, int cost):pos(pos),prev(prev),cost(cost){}

  bool operator>(const state &t)const{
    if(cost!=t.cost)return cost>t.cost;
    if(prev!=t.prev)return prev>t.prev;
    if(pos!=t.pos)return pos>t.pos;
    return false;
  }
};

typedef vector<edge> edges;
typedef vector<edges> graph;

int convTime(const string &s){
  int h = atoi(s.substr(0,2).c_str());
  int m = atoi(s.substr(3,2).c_str());
  return 60 * h + m;
}

string revTime(int t){
  char buf[32];
  sprintf(buf, "%02d:%02d", t/60, t%60);
  return string(buf);
}

static int dist[MAX_V][MAX_V];
void johnson(const graph &tmp_g){
  graph g = tmp_g;
  
  const int v = g.size();
  static int h[MAX_V];
  static int prev[MAX_V][MAX_V];
  

  for(int i = 0; i < v; ++i){
    h[i] = 0;
  }

  for(int i = 0; i <= v; ++i){
    bool end = true;
    for(int j = 0; j < v; ++j){
      for(int k = 0; k < (int)g[j].size(); ++k){
        edge e = g[j][k];
        int tmp = h[j] + e.cost;
        if( h[e.dst] > tmp ){
          h[e.dst] = tmp;
          end = false;
        }
      }
    }
    if(end)break;
    // do not detect an negative cycle.
  }

  for(int i = 0; i < v; ++i){
    for(int j = 0; j < v; ++j){
      dist[i][j] = inf;
      prev[i][j] = -1;
    }
    dist[i][i] = 0;
  }

  for(int i = 0; i < v; ++i){
    for(int j = 0; j < (int)g[i].size(); ++j){
      g[i][j].cost += h[i] - h[g[i][j].dst];
    }
  }

  for(int s = 0; s < v; ++s){
    priority_queue<state, vector<state>, greater<state> > q;
    q.push(state(s,s,0));
    while(!q.empty()){
      state cur = q.top(); q.pop();
      if(prev[s][cur.pos]!=-1)continue;
      prev[s][cur.pos] = cur.prev;
      for(int i = 0; i < (int)g[cur.pos].size(); ++i){
        edge e = g[cur.pos][i];
        int cost = cur.cost + e.cost;
        assert(cost>=0);
        if(dist[s][e.dst] > cost){
          dist[s][e.dst] = cost;
          q.push(state(e.dst,cur.pos,cost));
        }
      }
    }
    for(int i = 0; i < v; ++i){
      dist[s][i] += h[i] - h[s];
    }
  }

  return ;  
}

int main()
{
  int n;
  while(cin>>n && n){
    int id = 1;
    int vid = 0;
    map<string,int> cityDict;
    map<int,string> revCityDict;
    set<int> cityEvTimes[max_place];
    graph g(MAX_V);
    
    map<pair<int,int>, int> vID;
    map<int,pair<int,int> > revID;
    
    for(int i = 0; i < n; ++i){
      string from, ftime, to, ttime;
      int cost;

      cin >> from >> ftime >> to >> ttime >> cost;
      if(!cityDict.count(from)){
        cityDict[from] = id;
        revCityDict[id] = from;
        ++id;
      }
      if(!cityDict.count(to)){
        cityDict[to] = id;
        revCityDict[id] = to;
        ++id;
      }

      int src = cityDict[from];
      int dst = cityDict[to];
      int srcTime = convTime(ftime) - 480;
      int dstTime = convTime(ttime) - 480;
      
      if( dstTime >= 0 && dstTime < max_time && srcTime >= 0 && srcTime < max_time ){
        if( !vID.count(make_pair(src,srcTime)) ){
          vID[make_pair(src,srcTime)] = vid;
          revID[vid] = make_pair(src,srcTime);
          ++vid;
        }
        cityEvTimes[src].insert(srcTime);
        if( !vID.count(make_pair(dst,dstTime)) ){
          vID[make_pair(dst,dstTime)] = vid;
          revID[vid] = make_pair(dst,dstTime);
          ++vid;
        }
        cityEvTimes[dst].insert(dstTime);
        
        g[vID[make_pair(src,srcTime)]].push_back( edge(vID[make_pair(src,srcTime)], vID[make_pair(dst,dstTime)], cost) );
      }

    }
    g.resize(vID.size());
    
    for(int i = 1; i < id; ++i){
      foreach(it2, cityEvTimes[i]){
        set<int>::iterator it3 = it2;
        ++it3;
        if( it3 != cityEvTimes[i].end() ){
          g[vID[make_pair(i,*it2)]].push_back( edge(vID[make_pair(i,*it2)], vID[make_pair(i,*it3)], 0) );
        }
      }
    }
    
    johnson(g);

    int res = inf;
    int kenInitial = cityDict["Tokyo"];
    int keikoInitial = cityDict["Hakodate"];

    int ken_st, keiko_st;
    if( cityEvTimes[kenInitial].size() > 0 && cityEvTimes[keikoInitial].size() > 0 ){
      ken_st = vID[make_pair(kenInitial, *(cityEvTimes[kenInitial].begin()))];
      keiko_st = vID[make_pair(keikoInitial, *(cityEvTimes[keikoInitial].begin()))];

      for(int i = 1; i < id; ++i){
        foreach(ev1, cityEvTimes[i]){
          int v1 = vID[make_pair(i,*ev1)];
          foreach(ev2, cityEvTimes[i]){
            int v2 = vID[make_pair(i,*ev2)];
            int st = max(*ev1, *ev2) + 30;
            int from = -1;

            if(cityEvTimes[i].lower_bound(st)!=cityEvTimes[i].end()){
              from = vID[make_pair(i,*(cityEvTimes[i].lower_bound(st)))];
            }
            if(from<0)continue;
            foreach(ev3, cityEvTimes[kenInitial]){
              if( *ev3 < st ) continue;
              int v3 = vID[make_pair(kenInitial,*ev3)];
              foreach(ev4, cityEvTimes[keikoInitial]){
                if( *ev4 < st ) continue;
                int v4 = vID[make_pair(keikoInitial, *ev4)];
                res = min(res, dist[ken_st][v1] + dist[keiko_st][v2] + dist[from][v3] + dist[from][v4]);
              }
            }
          }
        }
      }
      
    }
 

    if(res>=inf)res = 0;
    cout << res << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 1650
memory_kb: 32480
final_rank: 12

code_snippet: #include<iostream>
#include<queue>
#include<string>
#include<map>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<set>
#include<cstdio>
#include<cassert>

using namespace std;

#define foreach(i,o) for(__typeof((o).begin()) i = (o).begin(); i != (o).end(); ++i)

const int max_place = 101;
const int max_time = 601;
const int MAX_V = 2010;
const int inf = 1<<28;

struct edge{
  int src, dst;
  int cost;
  edge(int src, int dst, int cost):src(src), dst(dst), cost(cost){}
};

struct state{
  int pos;
  int prev;
  int cost;
  
  state(int pos, int prev, int cost):pos(pos),prev(prev),cost(cost){}

  bool operator>(const state &t)const{
    if(cost!=t.cost)return cost>t.cost;
    if(prev!=t.prev)return prev>t.prev;
    if(pos!=t.pos)return pos>t.pos;
    return false;
  }
  
  /*
  bool operator<(const state &t)const{
    if(pos!=t.pos)return pos<t.pos;
    return false;
  }
  */
};

typedef vector<edge> edges;
typedef vector<edges> graph;

int convTime(const string &s){
  int h = atoi(s.substr(0,2).c_str());
  int m = atoi(s.substr(3,2).c_str());
  return 60 * h + m;
}

string revTime(int t){
  char buf[32];
  sprintf(buf, "%02d:%02d", t/60, t%60);
  return string(buf);
}

static int dist[MAX_V][MAX_V];
void johnson(const graph &tmp_g){
  graph g = tmp_g;
  
  const int v = g.size();
  static int h[MAX_V];
  static int prev[MAX_V][MAX_V];
  

  for(int i = 0; i < v; ++i){
    h[i] = 0;
  }

  for(int i = 0; i <= v; ++i){
    bool end = true;
    for(int j = 0; j < v; ++j){
      for(int k = 0; k < (int)g[j].size(); ++k){
        edge e = g[j][k];
        int tmp = h[j] + e.cost;
        if( h[e.dst] > tmp ){
          h[e.dst] = tmp;
          end = false;
        }
      }
    }
    if(end)break;
    // do not detect an negative cycle.
  }

  for(int i = 0; i < v; ++i){
    for(int j = 0; j < v; ++j){
      dist[i][j] = inf;
      prev[i][j] = -1;
    }
    dist[i][i] = 0;
  }

  for(int i = 0; i < v; ++i){
    for(int j = 0; j < (int)g[i].size(); ++j){
      g[i][j].cost += h[i] - h[g[i][j].dst];
    }
  }

  for(int s = 0; s < v; ++s){
    priority_queue<state, vector<state>, greater<state> > q;
    q.push(state(s,s,0));
    while(!q.empty()){
      state cur = q.top(); q.pop();
      if(prev[s][cur.pos]!=-1)continue;
      prev[s][cur.pos] = cur.prev;
      for(int i = 0; i < (int)g[cur.pos].size(); ++i){
        edge e = g[cur.pos][i];
        int cost = cur.cost + e.cost;
        assert(cost>=0);
        if(dist[s][e.dst] > cost){
          dist[s][e.dst] = cost;
          q.push(state(e.dst,cur.pos,cost));
        }
      }
    }
    for(int i = 0; i < v; ++i){
      dist[s][i] += h[i] - h[s];
    }
  }

  return ;  
}

int main()
{
  int n;
  while(cin>>n && n){
    int id = 1;
    int vid = 0;
    map<string,int> cityDict;
    map<int,string> revCityDict;
    set<int> cityEvTimes[max_place];
    graph g(MAX_V);
    
    map<pair<int,int>, int> vID;
    map<int,pair<int,int> > revID;
    
    for(int i = 0; i < n; ++i){
      string from, ftime, to, ttime;
      int cost;

      cin >> from >> ftime >> to >> ttime >> cost;
      if(!cityDict.count(from)){
        cityDict[from] = id;
        revCityDict[id] = from;
        ++id;
      }
      if(!cityDict.count(to)){
        cityDict[to] = id;
        revCityDict[id] = to;
        ++id;
      }

      int src = cityDict[from];
      int dst = cityDict[to];
      int srcTime = convTime(ftime) - 480;
      int dstTime = convTime(ttime) - 480;
      
      if( dstTime >= 0 && dstTime < max_time && srcTime >= 0 && srcTime < max_time ){
        if( !vID.count(make_pair(src,srcTime)) ){
          vID[make_pair(src,srcTime)] = vid;
          revID[vid] = make_pair(src,srcTime);
          ++vid;
        }
        cityEvTimes[src].insert(srcTime);
        if( !vID.count(make_pair(dst,dstTime)) ){
          vID[make_pair(dst,dstTime)] = vid;
          revID[vid] = make_pair(dst,dstTime);
          ++vid;
        }
        cityEvTimes[dst].insert(dstTime);
        
        g[vID[make_pair(src,srcTime)]].push_back( edge(vID[make_pair(src,srcTime)], vID[make_pair(dst,dstTime)], cost) );
      }

    }
    g.resize(vID.size());
    
    for(int i = 1; i < id; ++i){
      // sort( it->second.begin(), it->second.end() );
      foreach(it2, cityEvTimes[i]){
        // g[it->first].push_back( edge(it->first, it->second[i], it->first, it->second[i], 0) );
        set<int>::iterator it3 = it2;
        ++it3;
        if( it3 != cityEvTimes[i].end() ){
          g[vID[make_pair(i,*it2)]].push_back( edge(vID[make_pair(i,*it2)], vID[make_pair(i,*it3)], 0) );
        }
      }
    }
    

    /*
    for(int i = 0; i < (int)g.size(); ++i){
      cout << i << ' ' << revCityDict[i] << ':' << endl;
      for(int j = 0; j < (int)g[i].size(); ++j){
        edge e = g[i][j];
        cout << revCityDict[e.src] << ' ' << revTime(e.srcTime) << ' ' << revCityDict[e.dst] << ' ' << revTime(e.dstTime) << endl;
      }
    }
    cout << "---"<<endl;
    */

    /*
    foreach(i,revID){
      cout << revCityDict[i->second.first] << ' ' << revTime(i->second.second+480) << endl;
    }
    */

    johnson(g);

    /*
    for(int i = 0; i < (int)g.size(); ++i){
      for(int j = 0; j < (int)g.size(); ++j){
        cout << i << ' ' << j << " : " << dist[i][j]  <<endl;
      }
    }
    */

    int res = inf;
    int kenInitial = cityDict["Tokyo"];
    int keikoInitial = cityDict["Hakodate"];

    //cout << kenInitial << ' ' << keikoInitial << endl;

    int ken_st, keiko_st;
    if( cityEvTimes[kenInitial].size() > 0 && cityEvTimes[keikoInitial].size() > 0 ){
      ken_st = vID[make_pair(kenInitial, *(cityEvTimes[kenInitial].begin()))];
      keiko_st = vID[make_pair(keikoInitial, *(cityEvTimes[keikoInitial].begin()))];

      //cout <<ken_st << ' ' <<keiko_st << endl;
      
      for(int i = 1; i < id; ++i){
        foreach(ev1, cityEvTimes[i]){
          int v1 = vID[make_pair(i,*ev1)];
          foreach(ev2, cityEvTimes[i]){
            int v2 = vID[make_pair(i,*ev2)];
            int st = max(*ev1, *ev2) + 30;
            int from = -1;

            if(cityEvTimes[i].lower_bound(st)!=cityEvTimes[i].end()){
              from = vID[make_pair(i,*(cityEvTimes[i].lower_bound(st)))];
            }
            if(from<0)continue;

            //cout << v1 << ' ' << v2 << ' ' << from << endl;

            foreach(ev3, cityEvTimes[kenInitial]){
              if( *ev3 < st ) continue;
              int v3 = vID[make_pair(kenInitial,*ev3)];
              foreach(ev4, cityEvTimes[keikoInitial]){
                if( *ev4 < st ) continue;
                int v4 = vID[make_pair(keikoInitial, *ev4)];
                // cout << i << ' ' << revTime(*ev1+480) << ' ' << revTime(*ev2+480) << ' ' << revTime(*ev3+480) << ' ' << revTime(*ev4+480) << ' ' << revTime(st+480) << " : " << sssp[0][i][*ev1] << ' '<<sssp[1][i][*ev2]<<' '<<sssp[2][kenInitial][*ev3]<< ' ' <<sssp[2][keikoInitial][*ev4] << endl;
                res = min(res, dist[ken_st][v1] + dist[keiko_st][v2] + dist[from][v3] + dist[from][v4]);
              }
            }
          }
        }
      }
      
    }
 

    if(res>=inf)res = 0;
    cout << res << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 1680
memory_kb: 32476
final_rank: 14

code_snippet: #include <iostream>
#include <sstream>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

const int INF = (1<<28);
const int STR = (8*60);
const int LIM = (18*60);

class Train
{
public:
	int src,dst,dep,arv,cst;
	Train(int src, int dst, int dep, int arv, int cst)
		:src(src),dst(dst),dep(dep),arv(arv),cst(cst)
	{}
};

class State
{
public:
	int p,tm,cst,pvT, pvC;
	State(int p, int tm, int cst, int pvT, int pvC)
		:p(p),tm(tm),cst(cst),pvT(pvT),pvC(pvC)
	{}

	bool operator<(const State& s) const
	{
		if(cst != s.cst) return cst > s.cst;
		return tm > s.tm;
	}
};

typedef vector<Train> City;
typedef vector<vector<int> > Matrix;

int toMin(string s)
{
	stringstream ss(s);
	int h,m;
	char t;
	ss >> h >> t >> m;

	return h*60+m;
}

bool used[100][2005];

int dijkstra_go(int S, int T, int u, vector<City>& cities)
{
	priority_queue<State> q;

	for(int i=0; i<cities[S].size(); i++)
		q.push(State(cities[S][i].dst, cities[S][i].arv, cities[S][i].cst, i, S));

	memset(used, 0, sizeof(used));

	while(!q.empty()) {
		State s=q.top(); q.pop();
		if(used[s.pvC][s.pvT]) continue;
		used[s.pvC][s.pvT] = true;

		if(s.pvC == T && s.pvT == u) return s.cst-cities[s.pvC][s.pvT].cst;

		for(int i=0; i<cities[s.p].size(); i++) {
			Train t = cities[s.p][i];
			if(used[s.p][i]) continue;
			if(s.tm > t.dep) continue;
			if(i == u && s.p == T && s.tm + 30 > t.dep) continue;

			q.push(State(t.dst, t.arv, s.cst+t.cst, i, s.p));
		}
	}

	return INF;
}

int dijkstra_back(int S, int T, int u, vector<City>& cities)
{
	if(S == T) return 0;

	priority_queue<State> q;
	q.push(State(cities[S][u].dst, cities[S][u].arv, cities[S][u].cst, u, S));

	memset(used, 0, sizeof(used));

	while(!q.empty()) {
		State s = q.top(); q.pop();
		if(used[s.pvC][s.pvT]) continue;
		used[s.pvC][s.pvT] = true;

		if(s.p == T) return s.cst;

		for(int i=0; i<cities[s.p].size(); i++) {
			Train t = cities[s.p][i];
			if(used[s.p][i]) continue;
			if(s.tm > t.dep) continue;

			q.push(State(t.dst, t.arv, s.cst+t.cst, i, s.p));
		}
	}

	return INF;
}

int solve(int Hakodate, int Tokyo, vector<City>& cities)
{
	Matrix goKen(cities.size());
	for(int i=0; i<cities.size(); i++) {
		goKen[i].resize(cities[i].size());
		for(int j=0; j<cities[i].size(); j++) {
			goKen[i][j] = INF;
		}
	}

	Matrix backKen(goKen), goKeiko(goKen), backKeiko(goKen);

	for(int i=0; i<cities.size(); i++)
	for(int j=0; j<cities[i].size(); j++) {
		goKen[i][j] = dijkstra_go(Hakodate, i, j, cities);
		goKeiko[i][j] = dijkstra_go(Tokyo, i, j, cities);
		backKen[i][j] = dijkstra_back(i, Hakodate, j, cities);
		backKeiko[i][j] = dijkstra_back(i, Tokyo, j, cities);
	}

	int res = INF;
	for(int i=0; i<cities.size(); i++)
	for(int j=0; j<cities[i].size(); j++)
	for(int k=0; k<cities[i].size(); k++)
	{
		int g = (cities[i][j].dep < cities[i][k].dep ? j : k);
		res = min(res, goKeiko[i][g]+goKen[i][g]+backKeiko[i][j]+backKen[i][k]);
	}

	if(res == INF) res = 0;

	return res;
}

int main()
{
	int N;
	while(cin >> N, N) {
		
		int cnt=0;
		map<string, int> dic;
		vector<City> cities(N);
		for(int i=0; i<N; i++) {
			string src,dst,t,s;
			int c;
			cin >> src >> t >> dst >> s >> c;
			
			if(!dic.count(src)) dic[src] = cnt++;
			if(!dic.count(dst)) dic[dst] = cnt++;

			int l = toMin(t), r = toMin(s);
			if(l < STR || r < STR|| l > LIM || r > LIM) continue;

			cities[dic[src]].push_back(Train(dic[src], dic[dst], l, r, c));
		}

		int hako = dic["Hakodate"];
		int tokyo = dic["Tokyo"];

		cities[hako].push_back(Train(hako, hako, LIM, LIM, 0));
		cities[tokyo].push_back(Train(tokyo, tokyo, LIM, LIM, 0));

		cout << solve(hako, tokyo, cities) << endl;
	}

}
accuracy: 1
time_ms: 1880
memory_kb: 1396
final_rank: 7

code_snippet: #define INF 10000000
#define BIAS 24*60
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>

char gCity[2001][64];
int gCityNum = 0;
int from_hakodate[2001][101];
int to_hakodate[2001][101];
int from_tokyo[2001][101];
int to_tokyo[2001][101];

struct Train{
  int from, to;
  int dpt, arv;
  int fare;
};

int max(int lhs,int rhs){
  if(lhs > rhs) return lhs;
  else return rhs;
}

int min(int lhs,int rhs){
  if(lhs > rhs) return rhs;
  else return lhs;
}

int getCityNum(char* cityName){
  int i;
  for(i=0;i<gCityNum;i++){
    if(strcmp(gCity[i],cityName)==0) return i;
  }
  
  strcpy(gCity[gCityNum],cityName);
  return gCityNum++;
}

void setTrain(int idx,struct Train* trains,
	      int dptH,int dptM,int arvH,int arvM,int fare,
	      char dptCity[64],char arvCity[64]){
  trains[idx].from = getCityNum(dptCity);
  trains[idx].to = getCityNum(arvCity);
  trains[idx].dpt = dptH*60 + dptM;
  trains[idx].arv = arvH*60 + arvM;
  trains[idx].fare = fare;
}

void setRTrain(int idx,struct Train* trains,
	      int dptH,int dptM,int arvH,int arvM,int fare,
	      char dptCity[64],char arvCity[64]){
  trains[idx].from = getCityNum(arvCity);
  trains[idx].to = getCityNum(dptCity);
  trains[idx].dpt = BIAS - (arvH*60 + arvM);
  trains[idx].arv = BIAS - (dptH*60 + dptM);
  trains[idx].fare = fare;
}

int seekMaxFareTrain(struct Train* trains,int ub){
  int i;
  int maxFare = -1;
  int res;
  for(i=0;i<ub;i++){
    if(maxFare < trains[i].fare){
      maxFare = trains[i].fare;
      res = i;
    }
  }
  return res;
}

int seekMostDelayTrain(struct Train* trains,int ub){
  int i;
  int mostDelay = -1;
  int res;
  for(i=0;i<ub;i++){
    if(mostDelay < abs(trains[i].dpt - trains[i].arv)){
      mostDelay = abs(trains[i].dpt - trains[i].arv);
      res = i;
    }
  }
  return res;
}

int change(int city,int id,struct Train* trains){
  int i;
  for(i=id-1;i>=0;i--){
    if(trains[i].arv <= trains[id].dpt
       && trains[i].to == city){
      return i;
    }
  } 

  return 0;
}

int fr(char* name,int trainNum,int table[2001][101], struct Train* trains){
  int src = getCityNum(name);

  //printf("%s %d\n",name,src);

  table[0][src] = 0;
  int i;
  for(i=0;i<trainNum;i++){
    int j;
    for(j=0;j<gCityNum;j++){
      if(j==trains[i].to){
	table[i+1][j] = min(table[i][j],table[change(trains[i].from,i,trains)+1][trains[i].from]+trains[i].fare);
      }
      else table[i+1][j] = table[i][j];
    }
  }
}

void printTable(int table[2001][101],int n){
  int i;
  for(i=0;i<=n;i++){
    int j;
    for(j=0;j<gCityNum;j++){
      printf("%d ",table[i][j]);
    }
    printf("\n");
  }
}

int mycmp(const void* t1,const void* t2){
  return ((const struct Train*)t1)->arv - ((const struct Train*)t2)->arv;
}

void printTrains(struct Train* trains,int n){
  int i;
  for(i=0;i<n;i++){
    printf("%d %d %d %d %d\n",
	   trains[i].from,trains[i].dpt,trains[i].to,
	   trains[i].arv,trains[i].fare);
  }
}

int calc_cost(int city,struct Train* trains,struct Train* rtrains,int trainNum){
  int i;
  int res = INF;
  for(i=0;i<trainNum;i++){
    int j;
    for(j=trainNum-1;j>=0;j--){
      int stay = (BIAS - rtrains[j].arv) - trains[i].arv;
      if(stay < 30) continue;

      int c = from_hakodate[i+1][city]
	+ from_tokyo[i+1][city]
	+ to_hakodate[j+1][city]
	+ to_tokyo[j+1][city];
      res = min(res,c);
    }
  }
  return res;
}

int main(){
  int n;
  while(~scanf("%d",&n)){
    if(n==0) break;
    struct Train* trains = (struct Train*)malloc(n*sizeof(struct Train));
    struct Train* rtrains = (struct Train*)malloc(n*sizeof(struct Train));
    int i=0;
    int j=0;
    for(i=0,j=0;i<n;i++){
      int dptH,dptM,arvH,arvM,fare;
      char dptCity[64],arvCity[64];
      scanf("%s %d:%d %s %d:%d %d",dptCity,&dptH,&dptM,arvCity,&arvH,&arvM,&fare);
      if((dptH*60 + dptM < 8*60) || (arvH*60 + arvM > 18*60)) continue;
      setTrain(j,trains,dptH,dptM,arvH,arvM,fare,dptCity,arvCity);
      setRTrain(j++,rtrains,dptH,dptM,arvH,arvM,fare,dptCity,arvCity);
    }

    //    printTrains(trains,j);
    //    printf("\n");
    qsort(trains,j,sizeof(struct Train),mycmp);
    qsort(rtrains,j,sizeof(struct Train),mycmp);

    //    printTrains(trains,j);
    //    printf("\n");

    memset(from_hakodate,0x3,sizeof(from_hakodate));      
    fr("Hakodate",j,from_hakodate,trains);

    memset(from_tokyo,0x3,sizeof(from_tokyo));      
    fr("Tokyo",j,from_tokyo,trains);

    memset(to_hakodate,0x3,sizeof(to_hakodate));      
    fr("Hakodate",j,to_hakodate,rtrains);

    memset(to_tokyo,0x3,sizeof(to_tokyo));      
    fr("Tokyo",j,to_tokyo,rtrains);


    int mincost = INF;
    
    for(i=0;i<gCityNum;i++){
      mincost = min(calc_cost(i,trains,rtrains,j),mincost);
    }
    //printTable(to_hakodate,j);
    //printTable(to_tokyo,j);
    
    //printf("\n");
    //printf("cityname:%s cityid:%d\n",arvCity,getCityNum(arvCity));

    printf("%d\n",mincost == INF ? 0:mincost);

    memset(gCity,'\0',sizeof(gCity));
    gCityNum = 0;
    free(trains);
    free(rtrains);
  }
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 0
final_rank: 2

code_snippet: #include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <climits>
using namespace std;

typedef long long ll;

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

class E{
public:
  int to;
  int ft,tt;
  int cost;

  E(){}
  E(int _to,int _ft,int _tt,int _cost){
    to = _to;
    ft = _ft;
    tt = _tt;
    cost = _cost;
  }
};

class State{
public:
  int id,tm,cost;

  State(){}
  State(int _id,int _tm,int _cost){
    id = _id;
    tm = _tm;
    cost = _cost;
  }

  bool operator<(const State &st)const{
    return cost > st.cost;
  }
};

int n,m;
int A,B;
int LEAVE,BACK;
int ac[102][2000],bc[102][2000];
int r_ac[102][2000],r_bc[102][2000];
map<string,int> name;
vector<E> t[102],rt[102];

int TimeToInt(string s){
  int h = (s[0] - '0') * 10 + (s[1] - '0');
  int m = (s[3] - '0') * 10 + (s[4] - '0');
  return h * 60 + m;
}

int NameToInt(string s){
  int tmp = name[s];
  if(tmp == 0){
    name[s] = name.size();
  }
  return name[s];
}

void calCost(int start,int closed[102][2000]){
  priority_queue<State> open;
  rep(i,102) rep(j,2000) closed[i][j] = -1;
  open.push(State(start,LEAVE,0));

  while(!open.empty()){
    State st = open.top(); open.pop();
    if(closed[st.id][st.tm] != -1) continue;
    closed[st.id][st.tm] = st.cost;

    rep(i,t[st.id].size()){
      E e = t[st.id][i];
      if(st.tm <= e.ft){
        open.push(State(e.to,e.tt,st.cost+e.cost));
      }
    }
  }
}

void calRevCost(int start,int closed[102][2000]){
  priority_queue<State> open;
  rep(i,102) rep(j,2000) closed[i][j] = -1;
  open.push(State(start,BACK,0));

  while(!open.empty()){
    State st = open.top(); open.pop();
    if(closed[st.id][st.tm] != -1) continue;
    closed[st.id][st.tm] = st.cost;

    rep(i,rt[st.id].size()){
      E e = rt[st.id][i];
      if(st.tm >= e.ft){
        open.push(State(e.to,e.tt,st.cost+e.cost));
      }
    }
  }

  REP(i,1,n){
    int minCost = INT_MAX;
    for(int j=1999;j>=0;j--){
      if(closed[i][j] != -1){
        minCost = min(minCost,closed[i][j]);
      }
      closed[i][j] = (minCost == INT_MAX ? -1 : minCost);
    }
  }
}

int main(){
  LEAVE = TimeToInt("08:00");
  BACK = TimeToInt("18:00");

  while(cin>>m,m){
    name.clear();
    rep(i,102){
      t[i].clear();
      rt[i].clear();
    }

    rep(i,m){
      string from,to,ft,tt;
      int cost;
      cin>>from>>ft>>to>>tt>>cost;

      int fromID = NameToInt(from);
      int toID = NameToInt(to);
      int ft_int = TimeToInt(ft);
      int tt_int = TimeToInt(tt);

      t[fromID].push_back(E(toID,ft_int,tt_int,cost));
      rt[toID].push_back(E(fromID,tt_int,ft_int,cost));
    }

    n = name.size() + 1;
    A = NameToInt("Hakodate");
    B = NameToInt("Tokyo");

    calCost(A,ac);
    calCost(B,bc);

    calRevCost(A,r_ac);
    calRevCost(B,r_bc);

    int ans = INT_MAX;
    REP(i,1,n){
      REP(atime,LEAVE,BACK+1){
        if(ac[i][atime] == -1) continue;
        REP(btime,LEAVE,BACK+1){
          if(bc[i][btime] == -1) continue;
          int maxTime = max(atime,btime);
          if(r_ac[i][maxTime+30] == -1 || r_bc[i][maxTime+30] == -1) break;
          ans = min(ans,ac[i][atime] + bc[i][btime] + r_ac[i][maxTime+30] + r_bc[i][maxTime+30]);
        }
      }
    }
    cout<<(ans == INT_MAX ? 0 : ans)<<endl;

  }
}
accuracy: 1
time_ms: 10
memory_kb: 0
final_rank: 1

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <queue>

using namespace std;

int strToTime(string &s){
    return atoi(s.substr(0,2).c_str())*60 + atoi(s.substr(3,2).c_str());
}

struct edge{
    int cost;
    int start;
    int goal;
    int to;
    bool operator<(const edge &e)const{
        return start>e.start;
    }
};

vector<edge> G[101];

struct Sit{
    int cTime;
    int cost;
    int node;

    bool operator<(const Sit &s)const{
        return cTime>s.cTime;
    }
};

const int INF=1000000000;

int backMinCost(int idx,int sTime,int snode);

queue<Sit> *pprv;
queue<Sit> *nnxt;

int main(){
    pprv=new queue<Sit>();
    nnxt=new queue<Sit>();
    queue<Sit> *prv=new queue<Sit>();
    queue<Sit> *nxt=new queue<Sit>();

    int n;
    while(cin>>n&&n!=0){
        for(int i = 0; i < 101; i++)G[i].clear();
        map<string,vector<pair<int,int> > > startAndFinTimes;
        map<string,int> stationIdx;
        stationIdx["Tokyo"]=0;
        stationIdx["Hakodate"]=1;
        int idx=2;
        for(int i = 0; i < n; i++){
            string st,ft;
            string s1,s2;
            edge e;
            cin>>s1>>st>>s2>>ft>>e.cost;
            e.start=strToTime(st);
            e.goal=strToTime(ft);
            if(stationIdx.find(s1)==stationIdx.end())
                stationIdx[s1]=idx++;
            if(stationIdx.find(s2)==stationIdx.end())
                stationIdx[s2]=idx++;
            e.to=stationIdx[s2];
            G[stationIdx[s1]].push_back(e);
        }
        for(int i = 0; i < 101; i++)sort(G[i].begin(),G[i].end());

        map<int,int> minCosts[2][101];
        for(int i = 0; i < 2; i++){
            Sit ss;
            ss.cost=0;
            ss.cTime=480;
            ss.node=i;
            prv->push(ss);
            minCosts[i][ss.node][ss.cTime]=0;
            while(prv->size()){
                while(prv->size()){
                    Sit s=prv->front();prv->pop();
                    for(int ii = 0; ii < G[s.node].size(); ii++){
                        edge &e=G[s.node][ii];
                        // ÔÍÇñÇñ¬³­ÈÁÄ¢­ÌÅ
                        if(e.start<s.cTime)
                            break;
                        if(e.start>60*18||e.goal>60*18)
                            continue;
                        Sit ns=s;
                        ns.cost+=e.cost;
                        ns.cTime=e.goal;
                        ns.node=e.to;
                        if(minCosts[i][ns.node].find(ns.cTime)!=minCosts[i][ns.node].end()){
                            if(minCosts[i][ns.node][ns.cTime]>ns.cost){
                                minCosts[i][ns.node][ns.cTime]=ns.cost;
                                nxt->push(ns);
                            }
                        }
                        else{
                            minCosts[i][ns.node][ns.cTime]=ns.cost;
                            nxt->push(ns);
                        }
                    }
                }
                swap(prv,nxt);
            }
        }
        int minCost=INF;
        for(int i = 0; i < idx; i++){
            for(map<int,int>::iterator it=minCosts[0][i].begin();it!=minCosts[0][i].end();it++){
                for(map<int,int>::iterator iit=minCosts[1][i].begin();iit!=minCosts[1][i].end();iit++){
                    int sum=it->second+iit->second;
                    int nextStartTime=max(it->first,iit->first)+30;
                    int res=backMinCost(0,nextStartTime,i);
                    int res2=backMinCost(1,nextStartTime,i);
                    if(res!=INF&&res2!=INF){
                        sum+=res+res2;
                        minCost=min(minCost,sum);
                    }
                }
            }
        }
        if(minCost==INF)cout<<0<<endl;
        else cout<<minCost<<endl;
    }
    delete prv;
    delete nxt;
    delete nnxt;
    delete pprv;
    return 0;
}

int backMinCost(int idx,int sTime,int snode){
    map<int,int> d[101];
    Sit ss;
    ss.cost=0;
    ss.node=snode;
    ss.cTime=sTime;
    pprv->push(ss);
    d[snode][ss.cTime]=ss.cost;
    while(pprv->size()){
        while(pprv->size()){
            Sit s=pprv->front();pprv->pop();
            for(int ii = 0; ii < G[s.node].size(); ii++){
                edge &e=G[s.node][ii];
                // ÔÍÇñÇñ¬³­ÈÁÄ¢­ÌÅ
                if(e.start<s.cTime)
                    break;
                if(e.start>60*18||e.goal>60*18)
                    continue;
                Sit ns=s;
                ns.cost+=e.cost;
                ns.cTime=e.goal;
                ns.node=e.to;
                if(d[ns.node].find(ns.cTime)!=d[ns.node].end()){
                    if(d[ns.node][ns.cTime]>ns.cost){
                        d[ns.node][ns.cTime]=ns.cost;
                        nnxt->push(ns);
                    }
                }
                else{
                    d[ns.node][ns.cTime]=ns.cost;
                    nnxt->push(ns);
                }
            }
        }
        swap(pprv,nnxt);
    }
    int res=INF;
    for(map<int,int>::iterator it=d[idx].begin();it!=d[idx].end();it++)
        res=min(res,it->second);
    return res;
}
accuracy: 1
time_ms: 6760
memory_kb: 1064
final_rank: 11

code_snippet: #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;

  }
}
accuracy: 1
time_ms: 20
memory_kb: 3392
final_rank: 3