#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

const int MaxN = 300+5;
const int MaxM = 1e4+5;
int Sum = 0;
int ansMax = -1e6;

struct _Edge{
    int u;
    int v;
    int c;
}Edge[MaxM];

template<typename  T>
struct _Union{
    const int maxN=MaxM;
    T f[MaxM];
    _Union(){
        for (T i=0; i<maxN; i++) {
            f[i]=i;
        }
    }
    T find(T n){
        if (f[n]==n) {
            return n;
        }else {
            T father = find(f[n]);
            f[n]=father;
            return father;
        }
    }
    void merge(T a,T b){
        f[find(b)] = find(a);
    }
};

_Union<int> Union;

int main(){
    int n,m;
    cin>>n>>m;
    for (int i=1; i<=m; i++) {
        cin>>Edge[i].u>>Edge[i].v>>Edge[i].c;
    }
    sort(Edge+1,Edge+1+m,[](_Edge a,_Edge b){return a.c<b.c;});
    for (int i=1; i<=m && Sum<= n-1; i++) {
        if (Union.find(Edge[i].u)!=Union.find(Edge[i].v)) {
            Union.merge(Edge[i].u, Edge[i].v);
            Sum++;
            ansMax=max(ansMax,Edge[i].c);
        }
    }
    cout<<n-1<<" "<<ansMax<<endl;
}