/*
TASK:wireless
LANG:C++
*/

#include <stdio.h>
#include <vector>
using namespace std;

const int inf = 1023456789;
const int N = 4*1024;

struct Type{
	Type(){}
  Type(int _neib, int _ener){
   	neib = _neib;
    ener = _ener;
  }
	int neib;
  int ener;
};

vector<Type> res1;
vector<Type> res2;
int sum1, sum2;


vector<int> ret;
int END;
bool first = true;


vector<Type> data[N];
int energy[N];
int distB[N], distC[N];

int i, j, n;
int a, b, c;

void Input(){

	//freopen("wireless.in", "rt", stdin);
  //printf("--\n");

	scanf("%d%d%d%d", &n, &a, &b, &c);
  for(i=1; i<=n; i++){
  	int m;
    scanf("%d", &m);
    data[i].resize(m);
    
    for(j=1; j<=m; j++){
    	int neib, ener;
      scanf("%d%d", &neib, &ener);
      data[i][j-1] = Type(neib, ener);
    }
  }
  
}


void PrintData(){
	for(i=1; i<=n; i++){
  	for(j=0; j<data[i].size(); j++)
    	printf("(%d,%d) ", data[i][j].neib, data[i][j].ener);
		printf("\n");
  }
}

void Djkstra(int start, int end){
	bool used[N];
  int dist[N];
  Type prev[N];

  for(i=0; i<=n; i++){
  	used[i] = 0;
    dist[i] = inf;
  }

  for(i=1; i<=n; i++)
  	if(energy[i])
    	for(j=0; j<data[i].size(); j++)
      	if(data[i][j].ener <= energy[i]){
        	dist[ data[i][j].neib ] = 0;
          prev[ data[i][j].neib ].neib = 0;
          prev[ data[i][j].neib ].ener = 0;
          
        }
  
  int best = start;
  dist[best] = 0;

  while(best != end){

    used[best] = 1;
    
  	for(i=0; i<data[best].size(); i++)
    	if(dist[ data[best][i].neib ] > dist[best] + data[best][i].ener){
      	dist[ data[best][i].neib ] = dist[best] + data[best][i].ener;
        prev[ data[best][i].neib ].neib = best;
        prev[ data[best][i].neib ].ener = i;
      }

    best = 0;

		for(i=1; i<=n; i++)
    	if(!used[i] && dist[i] < dist[best])
      	best = i;
  }
 // printf("DIST = %d\n", dist[end]);
  while(end != start && end != 0){

  	int p = prev[end].neib;
    int q = prev[end].ener;
    energy[p]  = max(energy[p], data[p][q].ener);
		ret.push_back(p);
 //   printf("%d ", p);
    end = p;
  }

  if(first){
  	END = ret.size();
  }
  first = false;
  /*
  printf("ENERGY ---\n");
  for(i=0; i<=n; i++)
  	printf("%d ", energy[i]);
	printf("\n");
  */
}

void Output1(){

  for(i=1; i<=n; i++)
  	sum1 += energy[i];

	for(i=END-1; i>=0; i--)
  	if(energy[ ret[i] ] > 0){
      res1.push_back(Type(ret[i], energy[ret[i]]));
      energy[ ret[i] ] = 0;
    }
    
	for(i=ret.size()-1; i>=END; i--)
  	if(energy[ ret[i] ] > 0){
      res1.push_back(Type(ret[i], energy[ret[i]]));
      energy[ ret[i] ] = 0;
    }
}

void Output2(){

  for(i=1; i<=n; i++)
  	sum2 += energy[i];

	for(i=END-1; i>=0; i--)
  	if(energy[ ret[i] ] > 0){
      res2.push_back(Type(ret[i], energy[ret[i]]));
      energy[ ret[i] ] = 0;
    }
    
	for(i=ret.size()-1; i>=END; i--)
  	if(energy[ ret[i] ] > 0){
      res2.push_back(Type(ret[i], energy[ret[i]]));
      energy[ ret[i] ] = 0;
    }


}


int main(){
	Input();
  data[0].push_back(Type(0,0));

  //PrintData();//for debug mode

  Djkstra(a, b);
  Djkstra(a, c);
  Output1();

  for(i=0; i<=n; i++)
  	energy[i] = 0;
  first = true;
  ret.clear();
  Djkstra(a, c);
  Djkstra(a, b);
  Output2();

  if(sum1 < sum2){
		printf("%d %d\n", res1.size(), sum1);
	  for(i=0; i<res1.size(); i++)
  		printf("%d %d\n", res1[i].neib, res1[i].ener);
  }
  else{
	  printf("%d %d\n", res2.size(), sum2);
  	for(i=0; i<res2.size(); i++)
  		printf("%d %d\n", res2[i].neib, res2[i].ener);

  }

  return 0;
}



