/*
TASK: wireless
LANG: C
*/

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

#define N 4096
#define M 1000100
#define inf 1e9

struct es {
	short a;
	short b;
	int c;
} fe[M], re[M];
int ec;
int feb[N], reb[N];

int ps[N];
int pd1[N];
int pd2[N];

unsigned int dd1[N];
unsigned int dd2[N];
unsigned int ds[N];

int ls[N];
int ld1[N];
int ld2[N];

int cd1[N];
int cd2[N];

int v[N];

int n, s, d1, d2;
int sp;


int cmpe(const void *a, const void *b) {
	if (((struct es*)a)->a == ((struct es*)b)->a)
		return (int) ((struct es*)a)->b - ((struct es*)b)->b;
		
        return (int) ((struct es*)a)->a - ((struct es*)b)->a;
}

void dijkstra_s() {
	int i, j;
	int m;

	for (i = 0; i <= n; i++) {
		ds[i] = inf;
		v[i] = 0;
        }
        ds[s] = 0;

	while (1) {
		m = 0;
		for (i = 1; i <= n; i++)
			if ((v[i] == 0) && (ds[i] < ds[m]))
				m = i;
		if (m == 0)
			break;
                v[m] = 1;

                for (j = feb[m]; fe[j].a == m; j++) {
			if (v[fe[j].b] == 1) continue;
			if (ds[m] + fe[j].c < ds[fe[j].b]) {
				ds[fe[j].b] = ds[m] + fe[j].c;
				ps[fe[j].b] = m;
				ls[fe[j].b] = ls[m]+1;
			}
		}
	}
}

void dijkstra_d1() {
	int i, j;
	int m;

	for (i = 0; i <= n; i++) {
		dd1[i] = inf;
		v[i] = 0;
        }
        dd1[d1] = 0;

	while (1) {
		m = 0;
		for (i = 1; i <= n; i++)
			if ((v[i] == 0) && (dd1[i] < dd1[m]))
				m = i;
		if (m == 0)
			break;
                v[m] = 1;

                for (j = reb[m]; re[j].a == m; j++) {
			if (v[re[j].b] == 1) continue;
			if (dd1[m] + re[j].c < dd1[re[j].b]) {
				dd1[re[j].b] = dd1[m] + re[j].c;
				pd1[re[j].b] = m;
				ld1[re[j].b] = ld1[m] + 1;
				cd1[re[j].b] = re[j].c;
			}
		}
	}
}

void dijkstra_d2() {
	int i, j;
	int m;

	for (i = 0; i <= n; i++) {
		dd2[i] = inf;
		v[i] = 0;
        }
        dd2[d2] = 0;

	while (1) {
		m = 0;
		for (i = 1; i <= n; i++)
			if ((v[i] == 0) && (dd2[i] < dd2[m]))
				m = i;
		if (m == 0)
			break;
                v[m] = 1;

                for (j = reb[m]; re[j].a == m; j++) {
			if (v[re[j].b] == 1) continue;
			if (dd2[m] + re[j].c < dd2[re[j].b]) {
				dd2[re[j].b] = dd2[m] + re[j].c;
				pd2[re[j].b] = m;
				ld2[re[j].b] = ld2[m] + 1;
				cd2[re[j].b] = re[j].c;
			}
		}
	}
}

void print_path_s(int m) {
	int i;
	
	if (m == s)
		return;
        print_path_s(ps[m]);
	
	for (i = feb[ps[m]]; fe[i].a == ps[m]; i++)
		if (fe[i].b == m) break;
        printf("%d %d\n", (int) fe[i].a, fe[i].c);
}

void print_path_d1(int m) {
	if (m == d1)
		return;
        printf("%d %d\n", m, cd1[m]);
	print_path_d1(pd1[m]);
}

void print_path_d2(int m) {
	if (m == d2)
		return;
		
        printf("%d %d\n", m, cd2[m]);
	print_path_d2(pd2[m]);
}


void solve() {
	int i;
	int m;
	int t1, t2;
	
	dijkstra_s();
	dijkstra_d1();
	dijkstra_d2();

	m = 0;
	for (i = 1; i <= n; i++) {
		if (cd1[i] < cd2[i]) t1 = cd1[i]; else t1 = cd2[i];
		if (cd1[m] < cd2[m]) t2 = cd1[m]; else t2 = cd2[m];
		
		if (ds[i]+dd1[i]+dd2[i]-t1 < ds[m]+dd1[m]+dd2[m]-t2)
			m = i;
        }

	sp = m;
	if (cd1[m] < cd2[m]) {
		t2 = cd1[m];
		cd1[m] = cd2[m];
        } else {
		t2 = cd2[m];
		cd2[m] = cd1[m];
        }
        if ((m != d1) && (m != d2)) t1 = 1; else t1 = 0;
	
        printf("%d %d\n", ls[m]+ld1[m]+ld2[m]-t1, ds[m]+dd1[m]+dd2[m]-t2);
	print_path_s(m);
	print_path_d1(m);
	if (m != d1 && m != d2)
                print_path_d2(pd2[m]);
        else
                print_path_d2(m);
}

int main() {
	int i, j;
	int t1, t2, t3;
	
	scanf("%d%d%d%d", &n, &s, &d1, &d2);
	for (i = 1; i <= n; i++) {
		scanf("%d", &t1);
		for (j = 0; j < t1; j++) {
			scanf("%d%d", &t2, &t3);
			fe[ec].a = i;
			fe[ec].b = t2;
			fe[ec].c = t3;
			re[ec].a = t2;
			re[ec].b = i;
			re[ec].c = t3;
			ec++;
        	}
	}
	qsort(fe, ec, sizeof(struct es), cmpe);
	qsort(re, ec, sizeof(struct es), cmpe);
	for (j = 1; j < ec; j++) {
		if (fe[j].a != fe[j-1].a)
			feb[fe[j].a] = j;
                if (re[j].a != re[j-1].a)
			reb[re[j].a] = j;
        }

        solve();
			
	return 0;
}
