Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Problem C:
TransferTrain

うなぎは電車に乗るのが好きである. いま，うなぎは駅 A から駅 B へ電車を使って行こうとしている. うなぎは急いでいるので, 最短時間の経路を選ぶことにした. ただし，うなぎは乗り換えが苦手なので, 最短時間の経路が複数ある場合は最も乗り換え回数の少ない経路を選ぶことにした.

$N$ 本の路線がある. $i$ 本目の路線は $a_i$ 個の駅を通っている. $i$ 本目の路線の通る駅名は通る順に $s_{i,0}, ... , s_{i,a_i -1}$ であり, 駅間の所要時間は $t_{i,0}, ..., t_{i,a_i - 2}$ である. 電車は路線上を上下方向に走っており, 入力で与えられた逆順に乗ることもできる. 複数の路線の同じ駅名は同じ駅を表しており，乗り換えをすることが出来る. 乗り換えには駅や路線によらず $T$ 分かかる.

一本の路線が同じ駅を複数回通ることもある．もし同じ路線，同じ駅の，路線内で異なる位置の駅に移動したい場合は乗り換えをする必要がある. たとえば, C - D - E - F - D - G という路線を使って C から G まで行く場合, 始点から終点まで一本の電車で行くことも，D 駅で乗り換えて C - D, D - G と乗ることもできる.

うなぎが駅 A から駅 B へ行くのにかかる時間と乗り換え回数を求めよ. 電車はとても頻繁に来るので待ち時間は無視してよい.

Constraints

$N$ will be between 1 and 50,000, inclusive.

$T$ will be an integer between 1 and 1,000, inclusive.

At least one train stops at A.

At least one train stops at B.

A and B will be distinct.

$a_i$ will be bigger than or equal to 2.

$a_1 + ... + a_N$ will be between 2 and 100,000, inclusive.

$s_{i,j}$ will contain between 1 and 10 characters, inclusive.

Each character in $s_{i,j}$ will be a letter ('A'-'Z', 'a'-'z').

$t_{i,j}$ will be an integer between 1 and 1,000, inclusive.

Input

入力は以下の形式で与えられる:

$N$ $T$

$A$ $B$

$a_1$

$s_{1,1}$ ... $s_{1,a_1}$

$t_{1,1}$ ... $t_{1,a_1 -1}$

...

$a_N$

$s_{N,1}$ ... $s_{N,a_N}$

$t_{N,1}$ ... $t_{N,a_N-1}$

Output

うなぎが駅 A から駅 B へ行くのにかかる時間と乗り換え回数を空白で区切って1 行に出力せよ.

Sample Input 1

2 10
Warsaw Petersburg
3
Kiev Moscow Petersburg
150 120
3
Moscow Minsk Warsaw
100 150

Sample Output 1

380 1

Sample Input 2

2 10
Warsaw Petersburg
3
Kiev Moscow Petersburg
150 120
2
Minsk Warsaw
150

Sample Output 2

-1

Solution in C (judge verdict: Accepted)

// AOJ 2371 TransferTrain
// 2018.2.24 bal4u

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// hash function library
#define HASHSIZ 200017
typedef struct { char *s; int id; } HASH;
HASH hash[HASHSIZ+2], *hashend = hash + HASHSIZ;

int insert(char *s, int id)
{
	unsigned long long i = 0;
	char *p = s;
	HASH *tp;

	while (*p) i = (i<<6) + *p++;
	tp = hash + (int)(i % HASHSIZ);
	while (tp->s != NULL) {
		if (!strcmp(tp->s, s)) return tp->id;
		if (++tp == hashend) tp = hash;
	}
	tp->s = s, tp->id = id;
	return -1;
}

// Priority Queue library
#define QMAX 150000
typedef struct { int s, tm; short tr; } QUE;
QUE que[QMAX]; int qsize;

#define PARENT(i) ((i)>>1)
#define LEFT(i)   ((i)<<1)
#define RIGHT(i)  (((i)<<1)+1)

void min_heapify(int i)
{
	int l, r, min;
	QUE qt;

	l = LEFT(i), r = RIGHT(i);
	if (l < qsize && (que[l].tm < que[i].tm ||
		que[l].tm == que[i].tm && que[l].tr < que[i].tr)) min = l; else min = i;
	if (r < qsize && (que[r].tm < que[min].tm ||
		que[r].tm == que[min].tm && que[r].tr < que[min].tr)) min = r;
	if (min != i) {
		qt = que[i], que[i] = que[min], que[min] = qt;
		min_heapify(min);
	}
}

void deq()
{
	que[0] = que[--qsize];
	min_heapify(0);
}

void enq(int s, int tm, int tr)
{
	int i, min;
	QUE qt;

	i = qsize++;
	que[i].s = s, que[i].tm = tm, que[i].tr = tr;
	while (i > 0 && (que[min = PARENT(i)].tm > que[i].tm ||
		que[min].tm == que[i].tm && que[min].tr > que[i].tr)) {
		qt = que[i], que[i] = que[min], que[min] = qt;
		i = min;
	}
}

#define MAX 150002
char name[MAX][11]; int sz;
int  trSta[MAX];
int lim[MAX], hi[MAX]; int *to[MAX]; short *tm[MAX]; char *tr[MAX];
char mk[MAX];

//#define getchar_unlocked()  getchar()
int in()
{
	int n = 0;
	int c = getchar_unlocked();
	do n = (n<<3)+(n<<1) + (c & 0xf), c = getchar_unlocked();
	while (c >= '0');
	return n;
}

void ins(char *s)
{
	while ((*s = getchar_unlocked()) > ' ') s++;
	*s = 0;
}

void getmem(int k, int lim, int mode)
{
	if (mode) {			// realloc
		to[k] = realloc(to[k], lim << 2);	// int
		tm[k] = realloc(tm[k], lim << 1);	// short
		tr[k] = realloc(tr[k], lim);		// char
	} else {
		to[k] = malloc(lim << 2);
		tm[k] = malloc(lim << 1);
		tr[k] = malloc(lim);
		hi[k] = 0;
	}
}

int dijkstra(int *atm, int *atr, int start, int goal)
{
	int i, s, _tm, _tr, e;

	qsize = 0;
	enq(start, 0, 0);
	while (qsize) {
		s = que[0].s, _tm = que[0].tm, _tr = que[0].tr, deq();
		if (s == goal) { *atm = _tm, *atr = _tr; return 1; }

		if (mk[s]) continue;
		mk[s] = 1;

		for (i = 0; i < hi[s]; i++) {
			e = to[s][i];
			if (mk[e]) continue;
			enq(e, _tm + tm[s][i], _tr + tr[s][i]);
		}
	}
	return 0;
}

int main()
{
	int N, T, a, t, i, j, k, s, e, atm, atr;
	int *memo;

	N = in(), T = in();

	/* start/goal station */
	ins(name[0]);
	ins(name[1]);

	sz = 2;
	memo = malloc(MAX << 2);
	while (N--) {
		a = in(); for (i = 0; i < a; i++) {
			ins(name[sz]);
			k = insert(name[sz], sz);
			if (k < 0) {
				k = sz++;
				memo[i] = k;
				getmem(k, lim[k] = 2, 0);
			} else {		// if (k >= 0)
				if (!trSta[k]) {
					trSta[k] = s = sz++;
					getmem(k, lim[k] += 2, 1);
					getmem(s, lim[s] = 4, 0);
					j = hi[k]++, to[k][j] = s, tm[k][j] = T, tr[k][j] = 1;
					j = hi[s]++, to[s][j] = k, tm[s][j] = 0, tr[s][j] = 0;
				} else {
					s = trSta[k];
					if (hi[s] >= lim[s]) {
						k = lim[s]; if (k > 10000) k = 10000;
						lim[s] += k;
						getmem(s, lim[s], 1);
					}
				}

				memo[i] = e = sz++;
				getmem(e, lim[e] = 4, 0);
				j = hi[s]++, to[s][j] = e, tm[s][j] = 0, tr[s][j] = 0;
				j = hi[e]++, to[e][j] = s, tm[e][j] = T, tr[e][j] = 1;
			}
		}
		s = memo[0]; for (i = 1; i < a; i++) {
			e = memo[i], t = in();
			k = hi[s]++, to[s][k] = e, tm[s][k] = t, tr[s][k] = 0;
			k = hi[e]++, to[e][k] = s, tm[e][k] = t, tr[e][k] = 0;
			s = e;
		}
	}
	free(memo);

	atm = atr = 0;
	s = insert(name[0], 0);
	if (trSta[s] > 0) s = trSta[s];
	e = insert(name[1], 1);
	if (trSta[e] > 0) e = trSta[e], atm = -T, atr = -1;

	if (dijkstra(&i, &j, s, e)) printf("%d %d\n", atm+i, atr+j);
	else puts("-1");
	return 0;
}