#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<b;i++)
#define rrep(i,a,b) for(int i=a;i>=b;i--)
#define fore(i,a) for(auto &i:a)
#define all(x) (x).begin(),(x).end()
#pragma GCC optimize ("-O3")
using namespace std; void _main(); int main() { cin.tie(0); ios::sync_with_stdio(false); _main(); }
typedef long long ll; const int inf = INT_MAX / 2; const ll infl = 1LL << 60;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a = b; return 1; } return 0; }
//---------------------------------------------------------------------------------------------------
struct BridgeSCC {
    int NV = 0, time; vector<vector<int> > E; vector<int> ord, llink, inin;
    stack<int> roots, S; vector<int> M, ART; vector<vector<int> > SC; vector<pair<int, int> > BR;
    void init(int NV) { this->NV = NV; E.clear(); E.resize(NV); }
    void add_edge(int x, int y) { assert(NV); E[x].push_back(y); E[y].push_back(x); }
    void dfs(int cur, int pre) {
        int art = 0, conn = 0, i, se = 0; ord[cur] = llink[cur] = ++time;
        S.push(cur); inin[cur] = 1; roots.push(cur); rep(i, 0, E[cur].size()) {
            int tar = E[cur][i];
            if (ord[tar] == 0) {
                conn++; dfs(tar, cur); llink[cur] = min(llink[cur], llink[tar]);
                art += (pre != -1 && ord[cur] <= llink[tar]);
                if (ord[cur]<llink[tar]) BR.push_back(make_pair(min(cur, tar), max(cur, tar)));
            }
            else if (tar != pre || se) {
                llink[cur] = min(llink[cur], ord[tar]);
                while (inin[tar] && ord[roots.top()]>ord[tar]) roots.pop();
            }
            else se++;
        }
        if (cur == roots.top()) {
            SC.push_back(vector<int>()); while (1) {
                i = S.top(); S.pop(); inin[i] = 0; SC.back().push_back(i); M[i] = SC.size() - 1;
                if (i == cur) break;
            }sort(SC.back().begin(), SC.back().end()); roots.pop();
        }
        if (art || (pre == -1 && conn>1)) ART.push_back(cur);
    }
    void scc() {
        SC.clear(), BR.clear(), ART.clear(), M.resize(NV); ord.clear(), llink.clear(), inin.clear();
        time = 0; ord.resize(NV); llink.resize(NV); inin.resize(NV);
        for (int i = 0; i<NV; i++) if (!ord[i]) dfs(i, -1);
        sort(BR.begin(), BR.end()); sort(ART.begin(), ART.end());
    }
};
/*
ART : 関節点
SC : 二重辺連結成分
BR : 橋
*/
struct UnionFind {
    vector<int> par; // uf(x,y)->y
    UnionFind() {}
    UnionFind(int NV) { init(NV); }
    void init(int NV) { par.clear(); rep(i, 0, NV) par.push_back(i); }
    void reset() { rep(i, 0, par.size()) par[i] = i; }
    int operator[](int x) { return par[x] == x ? x : par[x] = operator[](par[x]); }
    void operator()(int x, int y) { x = operator[](x); y = operator[](y); if (x != y) par[x] = y; }
};
/*---------------------------------------------------------------------------------------------------
　　　　　　　　　　　 ∧＿∧  
　　　　　 ∧＿∧ 　（´<_｀ ）　 Welcome to My Coding Space!
　　　　 （ ´_ゝ`）　/　 ⌒i     
　　　　／　　　＼　 　 |　|     
　　　 /　　 /￣￣￣￣/　　|  
　 ＿_(__ﾆつ/　    ＿/ .| .|＿＿＿＿  
　 　　　＼/＿＿＿＿/　（u　⊃  
---------------------------------------------------------------------------------------------------*/



int N, M;
int U[101010], V[101010], W[101010];
ll cst[101010];
vector<pair<int,int>> E[101010];
//---------------------------------------------------------------------------------------------------
int dpt[101010]; ll sm[101010];
void dfs(int cu, int _dpt = 1) {
    dpt[cu] = _dpt;
    sm[cu] = cst[cu];
    fore(p, E[cu]) if (!dpt[p.first]) {
        dfs(p.first, _dpt + 1);
        sm[cu] += sm[p.first] + p.second;
    }
}
//---------------------------------------------------------------------------------------------------
void _main() {
    cin >> N >> M;
    rep(i, 0, M) cin >> U[i] >> V[i] >> W[i];
    rep(i, 0, M) U[i]--, V[i]--;

    BridgeSCC bs;
    bs.init(N);
    rep(i, 0, M) bs.add_edge(U[i], V[i]);
    bs.scc();

    UnionFind uf(N);
    fore(v, bs.SC) fore(i, v) uf(v.front(), i);

    ll mincst = infl;
    pair<int, int> ans = { U[0], V[0] };
    ll tot = 0;
    rep(m, 0, M) tot += W[m];
    rep(m, 0, M) if(uf[U[m]] == uf[V[m]]) {
        if (tot - W[m] < mincst) {
            mincst = tot - W[m];
            ans = { U[m], V[m] };
        }
        else if (tot - W[m] == mincst) chmin(ans, { U[m], V[m] });
    }

    if (1 < bs.SC.size()) {
        int root = 0;
        rep(m, 0, M) {
            if (uf[U[m]] == uf[V[m]]) cst[uf[U[m]]] += W[m];
            else {
                E[uf[U[m]]].push_back({ uf[V[m]], W[m] });
                E[uf[V[m]]].push_back({ uf[U[m]], W[m] });
                root = uf[U[m]];
            }
        }

        dfs(root);

        rep(m, 0, M) if (uf[U[m]] != uf[V[m]]) {
            int u = uf[U[m]], v = uf[V[m]];
            if (dpt[u] < dpt[v]) swap(u, v);
            ll uc = sm[u];
            ll vc = sm[root] - uc - W[m];

            ll cs = abs(uc - vc);
            if (cs < mincst) {
                mincst = cs;
                ans = { U[m], V[m] };
            }
            else if (cs == mincst) chmin(ans, { U[m], V[m] });
        }
    }

    printf("%d %d\n", ans.first + 1, ans.second + 1);
}


Measured memory_bytes: 25304