Problem:
E: 均衡な辺削除 (Balanced Edge Deletion)

問題

N 頂点 M 辺の重み付き単純無向グラフ G が与えられる。
頂点には 1 から N、 辺には 1 から M の番号がつけられている。
i 番目の辺は頂点 u_i と v_i を結んでおり、そのコストは w_i である。

このグラフに対して、以下の操作を 1 度だけ行うことを考える。

G の辺集合から辺を 1 つ選択し、その辺を削除する。

上の操作によってグラフが分割されることがあるので、操作後のグラフを A, B と表記することとする。(分割されない場合、B は空グラフであるとする。)
W(X) をグラフ X 内にある辺のコストの総和 (グラフに辺が存在しない場合 W(X)=0) とし、$\mathrm{cost}$(A,B)=|W(A)−W(B)| と定義する。$\mathrm{cost}$(A,B) が最小になるような辺 (u,v) を求めよ。複数存在する場合は、u が最小であるものを答えよ。それでも複数存在する場合は、v が最小であるものを答えよ。

入力形式

入力は以下の形式で与えられます。

N M
u_1 v_1 w_1
...
u_M v_M w_M

制約

2 \leq N \leq 10^5

1 \leq M \leq 10^5

1 \leq u_i < v_i \leq N

i \neq j ならば u_i \neq u_j または v_i \neq v_j

1 \leq w_i \leq 10^9

与えられるグラフは連結である。

出力形式

答えとなる辺を以下のように空白区切りで一行に出力せよ。

u v

u, v は整数

1 \leq u, v \leq N

入力例1

5 4
1 2 1
2 3 10
3 4 5
4 5 1

出力例1

2 3

入力例2

10 11
1 2 1
2 3 10
1 5 2
3 4 7
3 5 9
5 6 8
6 7 5
6 8 3
7 8 12
7 9 1
9 10 8

出力例2

5 6

Solution in C++14 (judge verdict: Accepted)

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;

#define FOR(i,bg,ed) for(int i=(bg);i<(ed);i++)
#define REP(i,n) FOR(i,0,n)

#define ALL(v) (v).begin(),(v).end()
#define REC(ret, ...) std::function<ret (__VA_ARGS__)>
template <typename T>inline bool chmin(T &l, T r) { bool a = l>r; if (a)l = r; return a; }
template <typename T>inline bool chmax(T &l, T r) { bool a = l<r; if (a)l = r; return a; }

int N, M;
int a[112345];
int b[112345];
LL c[112345];

int dep[112345];
int used[112345];
int br[112345];
int imos[112345];
using V = vector<int>;
using VV = vector<V>;
VV g;
void latte(int v,int pe,int d) {
	dep[v] = d;
	used[v] = 1;
	for (int e : g[v]) {
		if (e == pe)continue;
		int u = a[e] ^ b[e] ^ v;
		if(used[u]==0)latte(u, e, d + 1);
	}
}
void malta(int v, int pe) {
	used[v] = 1;
	for (int e : g[v]) {
		if (e == pe)continue;
		int u = a[e] ^ b[e] ^ v;
		if (used[u] == 1) {
			if (dep[u] < dep[v]) {
				imos[v]++;
				imos[u]--;
			}
		}
		else {
			malta(u, e);
			imos[v] += imos[u];
		}
	}
	if (imos[v]==0)br[pe] = 1;
}
using T = tuple<LL, int, int>;
T ans(0, 0, 0);
LL sum = 0;

LL sub[112345];
void beet(int v, int pe) {
	used[v] = 1;
	sub[v] = 0;
	for (int e : g[v]) {
		sub[v] += c[e];
		if (e == pe)continue;
		int u = a[e] ^ b[e] ^ v;
		if (used[u] == 0) {
			beet(u, e);
			sub[v] += sub[u];
			if (br[e]) {
				LL A = (sub[u] - c[e]) / 2;
				LL B = sum - A - c[e];
				//cout << abs(A - B) << " " << a[e] + 1 << " " << b[e] + 1 << endl;
				chmin(ans, T(abs(A - B), a[e] + 1, b[e] + 1));
			}

		}
	}
}
constexpr int NG = 112340;
int main() {
	cin >> N >> M;
	g = VV(N);
	REP(i, M) {
		cin >> a[i] >> b[i] >> c[i];
		a[i]--; b[i]--;
		g[a[i]].push_back(i);
		g[b[i]].push_back(i);
		sum += c[i];
	}
	ans = T(sum, 0, 0);
	REP(i, N)used[i] = 0;
	latte(0, NG, 0);
	REP(i, M)br[i] = 0;
	REP(i, N)used[i] = 0;
	REP(i, N)imos[i] = 0;
	malta(0, NG);
	REP(i, M) {
		if (br[i] == 0)chmin(ans, T(sum - c[i], a[i] + 1, b[i] + 1));
	}
	REP(i, N)used[i] = 0;
	beet(0, NG);
	LL x;
	int y, z;
	tie(x, y, z) = ans;
	cout << y << " " << z << endl;
	return 0;
}