#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#include <cstring>
#include <map>
using namespace std;

#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl;
#define EACH(i, s) for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ EACH(it, P) { s << "<" << *it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; } return s << endl; }


typedef pair<int,int> pint;

typedef pair<int, long long> Edge;
typedef vector<vector<Edge> > Graph;

namespace BD {
    vector<vector<int> > scc;
    Graph newG;
    vector<int> cmp;
    vector<pair<int,int> > bridges;
    vector<long long> weis;

    vector<int> ord, low, seen, parent;
    vector<int> comp;
    set<pair<int,int> > newGEdges;
    map<pint,pint> br;

    void dfs(const Graph &G, int v) {
        static int time = 0;
        seen[v] = true;
        ord[v] = low[v] = time++;
        for (int i = 0; i < (int)G[v].size(); ++i) {
            int to = G[v][i].first;
            if (seen[to]) {
                if (to != parent[v]) low[v] = min(low[v], low[to]);
                continue;
            }
            parent[to] = v;
            dfs(G, to);
            low[v] = min(low[v], low[to]);
            if (low[to] > ord[v]) {
                bridges.push_back(make_pair(v, to));
            }
        }
    }
    void MakeTreeDFS(const Graph &G, int v, int tempCmp) {
        seen[v] = true;
        cmp[v] = tempCmp;
        for (int i = 0; i < G[v].size(); ++i) {
            int to = G[v][i].first;
            long long wei = G[v][i].second;
            bool sameComp = true;
            if (seen[to]) sameComp = false;
            if (binary_search(bridges.begin(), bridges.end(), make_pair(v, to))
                || binary_search(bridges.begin(), bridges.end(), make_pair(to, v))) {
                sameComp = false;
            }
            if (!sameComp) {
                int toCmp = cmp[to];
                if (toCmp == -1) continue;
                if (toCmp != tempCmp) {
                    if (!newGEdges.count(make_pair(toCmp, tempCmp))
                        && !newGEdges.count(make_pair(tempCmp, toCmp))) {
                        newGEdges.insert(make_pair(tempCmp, toCmp));
                        newG[tempCmp].push_back(make_pair(toCmp, wei));
                        newG[toCmp].push_back(make_pair(tempCmp, wei));
                        br[pint(tempCmp, toCmp)] = pint(min(v, to), max(v, to));
                        br[pint(toCmp, tempCmp)] = pint(min(v, to), max(v, to));
                    }
                }
            }
            else {
                MakeTreeDFS(G, to, tempCmp);
            }
        }
        comp.push_back(v);
    }

    void solve(const Graph &G) {
        int N = G.size();
        cmp.resize(N);
        ord.resize(N);
        low.resize(N);
        seen.resize(N);
        parent.resize(N);
        for (int i = 0; i < N; ++i) {
            seen[i] = false;
            parent[i] = -1;
        }
        bridges.clear();
        for (int i = 0; i < N; ++i) {
            if (!seen[i]) {
                dfs(G, i);
            }
        }
        sort(bridges.begin(), bridges.end());
        scc.clear();
        newG.clear();
        newG.resize(N);
        newGEdges.clear();
        for (int i = 0; i < N; ++i) {
            seen[i] = false;
            cmp[i] = -1;
        }
        int tempCmp = 0;
        for (int v = 0; v < N; ++v) {
            if (seen[v]) continue;
            comp.clear();
            MakeTreeDFS(G, v, tempCmp);
            scc.push_back(comp);
            ++tempCmp;
        }
        newG.resize(tempCmp);
    }
};




long long all = 0;
vector<long long> node;
set<pair<pint,long long> > se;

long long res;
pint resb;
vector<long long> dp;
long long rec(const Graph &G, int v, int p = -1) {
    long long tmp = node[v];
    for (auto to : G[v]) {
        if (to.first == p) continue;
        rec(G, to.first, v);
    }

    for (auto to : G[v]) {
        if (to.first == p) continue;
        tmp += dp[to.first];
        tmp += to.second;
        long long val1 = dp[to.first];
        long long val2 = all - val1 - to.second;
        long long diff = abs(val1 - val2);


        //cout << v << ", " << to.first << ": " << val1 << ", " << val2 << endl;
        if (res > diff) {
            res = diff;
            resb = BD::br[pint(v, to.first)];
        }
        else if (res == diff) {
            if (resb > BD::br[pint(v, to.first)]) {
                resb = BD::br[pint(v, to.first)];
            }
        }
    }

    //cout << v << ": " << tmp << endl;

    return dp[v] = tmp;
}


int main() {
    int N, M;
    cin >> N >> M;
    Graph G(N);
    se.clear();
    all = 0;
    for (int i = 0; i < M; ++i) {
        int u, v;
        long long w;
        cin >> u >> v >> w;
        --u, --v;
        G[u].push_back(Edge(v, w));
        G[v].push_back(Edge(u, w));
        se.insert(make_pair(pint(u, v), w));
        all += w;
    }
    BD::solve(G);

    Graph ng = BD::newG;
    node.assign((int)ng.size(), 0);
    for (int v = 0; v < G.size(); ++v) {
        for (auto to : G[v]) {
            int u = to.first;
            if (BD::cmp[u] != BD::cmp[v]) continue;
            long long w = to.second;
            node[BD::cmp[u]] += w;
        }
    }
    for (int i = 0; i < node.size(); ++i) node[i] /= 2;

    /*
    COUT(ng);
    COUT(BD::cmp);
    COUT(BD::scc);
    COUT(BD::bridges);
    COUT(node);
    COUT(BD::br);
    */
    
    
        pint resb2 = make_pair(N, N);
        long long res2 = 1LL<<60;
        for (int v = 0; v < G.size(); ++v) {
            for (auto to : G[v]) {
                int u = to.first;
                pint tmp = make_pair(min(u, v), max(u, v));
                if (res2 > all - to.second) {
                    res2 = all - to.second;
                    resb2 = tmp;
                }
                else if (res2 == to.second) {
                    if (resb2 > tmp) resb2 = tmp;
                }
            }
        }
    

    res = 1LL<<60;
    if (node.size() > 1) {
        dp.assign(node.size(), 0);
        rec(ng, 0);

        //COUT(dp);
    }

    /*
    COUT(res);
    COUT(res2);
    COUT(resb);
    COUT(resb2);
    */

    if (res < res2) {
        cout << resb.first+1 << " " << resb.second+1 << endl;
    }
    else if (res == res2) {
        pint p = min(resb, resb2);
        cout << p.first+1 << " " << p.second + 1 << endl;
    }
    else {
        cout << resb2.first+1 << " " << resb2.second+1 << endl;
    }

}
        
                



Measured memory_bytes: 58132