#include<algorithm>
#include<cassert>
#include<cctype>
#include<climits>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<iomanip>
#include<map>
#include<numeric>
#include<queue>
#include<vector>
#include<set>
#include<string>
#include<stack>
#include<sstream>
#include<complex>

#define pb push_back
#define clr clear()
#define sz size()
#define fs first
#define sc second

#define rep(i,a) for(int i=0;i<(int)(a);i++)
#define rrep(i,a) for(int i=(int)(a)−1;i>=0;i−−)
#define all(a) (a).begin(),(a).end()
#define EQ(a,b) (abs((a)−(b)) < EPS)
#define INIT(a) memset(a,0,sizeof(a))

using namespace std;
typedef double D;
typedef pair<int,int> P;
typedef long long ll;
typedef vector<int> vi;
typedef vector<string> vs;

const D EPS = 1e-8;
const int INF = 1e8;
const D PI = acos(-1);

struct edge{
  int to,cost;
  bool operator<(const edge x)const{return cost>x.cost; }
};
int v; //頂点数
int d[20]; //s から i への最短路
vector<edge> G[20]; //ク&#12441;ラフの隣接リスト表現

void AddEdge(int s,int g,int p){
  G[s].pb((edge){g,p});
}


void BellmanFord(int s){
  fill(d,d+v,INF);
  d[s] = 0;
  for(;;){
    bool f = false; rep(i,v)rep(j,G[i].sz){
      edge e = G[i][j];
      if(d[i]<INF && d[e.to] > d[i] + e.cost){
	d[e.to] = d[i] + e.cost;
	f = true;
      }
    }
    if(!f)break;
  }
}

int n;
int a,b,c;

int main(){
  while(cin >> n,n){
    rep(i,20){
      G[i].clear();
    }

    v = 0;
    rep(i,n){
      cin >> a >> b >> c;
      v = max(v,max(a,b));
      AddEdge(a,b,c);
      AddEdge(b,a,c);
    }
    v++;

    int res = -1, dis = INF;
    rep(i,v){
      int tmp = 0;
      BellmanFord(i);
      rep(j,v)tmp += d[j];
      if(dis > tmp){
	dis = tmp; res = i;
      }
    }
    cout << res << " " << dis <<  endl;
  }
    
}