Problem:
E - Minimum Spanning Tree
Problem Statement
You are given an undirected weighted graph
G
with
n
nodes and
m
edges.
Each edge is numbered from
1
to
m
.
Let
G_i
be an graph that is made by erasing
i
-th edge from
G
. Your task is to compute the cost of minimum spanning tree in
G_i
for each
i
.
Input
The dataset is formatted as follows.
n
m
a_1
b_1
w_1
...
a_m
b_m
w_m
The first line of the input contains two integers
n
(
2 \leq n \leq 100{,}000
) and
m
(
1 \leq m \leq 200{,}000
).
n
is the number of nodes and
m
is the number of edges in the graph.
Then
m
lines follow, each of which contains
a_i
(
1 \leq a_i \leq n
),
b_i
(
1 \leq b_i \leq n
) and
w_i
(
0 \leq w_i \leq 1{,}000{,}000
).
This means that there is an edge between node
a_i
and node
b_i
and its cost is
w_i
.
It is guaranteed that the given graph is simple: That is, for any pair of nodes, there is at most one edge that connects them, and
a_i \neq b_i
for all
i
.
Output
Print the cost of minimum spanning tree in
G_i
for each
i
, in
m
line. If there is no spanning trees in
G_i
, print "-1" (quotes for clarity) instead.
Sample Input 1
4 6
1 2 2
1 3 6
1 4 3
2 3 1
2 4 4
3 4 5
Output for the Sample Input 1
8
6
7
10
6
6
Sample Input 2
4 4
1 2 1
1 3 10
2 3 100
3 4 1000
Output for the Sample Input 2
1110
1101
1011
-1
Sample Input 3
7 10
1 2 1
1 3 2
2 3 3
2 4 4
2 5 5
3 6 6
3 7 7
4 5 8
5 6 9
6 7 10
Output for the Sample Input 3
27
26
25
29
28
28
28
25
25
25
Sample Input 4
3 1
1 3 999
Output for the Sample Input 4
-1

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

const ll INF = 1e18;

struct ed {
    ll a, b, w, id;
};

bool operator<(ed a, ed b) {
    return a.w < b.w;
}

vector<ll> p;

ll get(ll x) {
    if (p[x] == x) {
        return p[x];
    }
    p[x] = get(p[x]);
    return p[x];
}

void join(ll x, ll y) {
    x = get(x), y = get(y);
    p[y] = x;
}

vector<vector<ll>> g, up;
vector<ll> tin, tout;
ll timer = 1;

void calc(ll v, ll pr) {
    tin[v] = timer++;
    up[v][0] = pr;
    for (int i = 1; i < 20; i++) {
        up[v][i] = up[up[v][i - 1]][i - 1];
    }

    for (auto u : g[v]) {
        if (u != pr) {
            calc(u, v);
        }
    }

    tout[v] = timer++;
}

ll lca(ll a, ll b) {
    if (tin[a] <= tin[b] && tout[a] >= tout[b]) {
        return a;
    }
    swap(a, b);
    if (tin[a] <= tin[b] && tout[a] >= tout[b]) {
        return a;
    }

    for (int i = 19; i >= 0; i--) {
        ll v = up[a][i];
        if (tin[v] <= tin[b] && tout[v] >= tout[b]) {
            continue;
        }
        a = v;
    }
    return up[a][0];
}

vector<multiset<ll>> elem;
void join2(ll x, ll y) {
    x = get(x), y = get(y);
    if (elem[x].size() < elem[y].size()) {
        swap(x, y);
    }
    for (auto el : elem[y]) {
        elem[x].insert(el);
    }
    p[y] = x;
}

vector<vector<ll>> add, del;
vector<ll> dp;

void dfs(ll v, ll pr) {
    for (auto u : g[v]) {
        if (u != pr) {
            dfs(u, v);
            join2(u, v);
        }
    }
    for (auto el : add[v]) {
        elem[get(v)].insert(el);
    }
    for (auto el : del[v]) {
        elem[get(v)].erase(elem[get(v)].find(el));
    }
    if (!elem[get(v)].empty()) {
        dp[v] = *elem[get(v)].begin();
    }
}

int main() {
    ll n, m;
    cin >> n >> m;
    vector<ed> edges;
    for (int i = 0; i < m; i++) {
        ll a, b, w;
        cin >> a >> b >> w;
        a--, b--;
        edges.push_back({a, b, w, i});
    }
    sort(edges.begin(), edges.end());
    p.resize(n);
    iota(p.begin(), p.end(), 0);

    g.resize(n);
    vector<ed> in, out;
    ll size = 0;
    ll col = 0;
    for (auto [a, b, w, id] : edges) {
        if (get(a) == get(b)) {
            out.push_back({a, b, w, id});
        } else {
            col++;
            join(a, b);
            size += w;
            g[a].push_back(b);
            g[b].push_back(a);
            in.push_back({a, b, w, id});
        }
    }

    if (col != n - 1) {
        for (int i = 0; i < m; i++) {
            cout << -1 << '\n';
        }
        return 0;
    }

    vector<ll> ans(m);
    up.resize(n, vector<ll>(20)),
    tin.resize(n), tout.resize(n);
    add.resize(n);
    del.resize(n);

    calc(0, 0);

    for (auto e : out) {
        ans[e.id] = size;
        ll a = e.a;
        ll b = e.b;
        ll w = e.w;
        ll lc = lca(a, b);
        add[a].push_back(w);
        del[lc].push_back(w);
        add[b].push_back(w);
        del[lc].push_back(w);
    }

    iota(p.begin(), p.end(), 0);
    elem.resize(n);
    dp.resize(n, INF);
    dfs(0, -1);

    for (auto e : in) {
        ll v = e.a, pr = e.b;
        if (tin[v] <= tin[pr] && tout[v] >= tout[pr]) {
            swap(v, pr);
        }
        ans[e.id] = size - e.w + dp[v];
    }

    for (int i = 0; i < m; i++) {
        if (ans[i] >= INF) {
            cout << -1 << '\n';
        } else {
            cout << ans[i] << '\n';
        }
    }
}
accuracy: 1
time_ms: 340
memory_kb: 91148
final_rank: 18

code_snippet: /**
 *	author:	 fractal
 *	timus: 	 288481RF
 *	created: 04/22/21 09:42
**/

#include <bits/stdc++.h>
using namespace std;

#define F first
#define S second 
#define mp make_pair
#define pb push_back
#define pf push_front
#define ppb pop_back
#define ppf pop_front
#define speed ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define sz(x) (int)x.size()
#define len(x) (int)strlen(x)
#define all(x) x.begin(), x.end()
#define debug cerr << "OK\n";
#define ub upper_bound
#define lb lower_bound 
#define nl printf("\n");
#define clbuff fflush(stdin);

mt19937 bruh(chrono::steady_clock::now().time_since_epoch().count());
mt19937_64 rofl(chrono::steady_clock::now().time_since_epoch().count());
 
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef set<int> si;
typedef set<ll> sll;
typedef set<pii> spii;
typedef set<pll> spll;
typedef multiset <int> msi;
typedef multiset <ll> msll;
typedef map <int, int> mi;
typedef map <ll, ll> mll;
 
const int N = 1e6 + 2;
const int M = 1e5;
const int mod = 1;
const int inf = 2e6;
const ll INF = 1e18;
const ld pi2 = 2.0 * 3.141592;
const ld pi = 3.141592;
const ld eps = 1e-12;

const int dx[4] = {1, -1, 0, 0};
const int dy[4] = {0, 0, -1, 1};

void files(string s = "main") {
	#ifndef PC
		freopen((s + ".in").c_str(), "r", stdin);
		freopen((s + ".out").c_str(), "w", stdout);
	#endif
}

int add(int a, int b) {
	if (a + b < 0) return a + b + mod;
	if (a + b >= mod) return a + b - mod;
	return a + b;		
}

int mul(int a, int b) {
	return a * 1LL * b % mod;
}

int binpow(int a, int n) {
	int ret = 1;
	while (n) {
		if (n & 1) ret = mul(ret, a);
		a = mul(a, a);
		n >>= 1;
	}
	return ret;
}

int n, m, sz[N], p[N], is[N], id[N], tin[N], tout[N], tick, ver[N];
pair <pii, pii> e[N];
vpii g[N], h[N];
ll ans, ret[N];

int get(int a) {
	return p[a] = (a == p[a] ? a : get(p[a]));
}

bool unite(int a, int b) {
	if ((a = get(a)) == (b = get(b)))
		return 0;
	if (sz[a] < sz[b]) swap(a, b);
	sz[a] += sz[b];
	p[b] = a;
	return 1;
}

void dfs(int v = 1, int p = 0) {
	tin[v] = ++tick;
	ver[tick] = v;
	for (auto to : g[v]) {
		if (to.F == p)
			continue;
		id[to.F] = to.S;
		dfs(to.F, v);
	}
	tout[v] = tick;
}

struct tree {
	
	vpii t[N];
	vi p[N], s[N];
	
	void build(int v = 1, int tl = 1, int tr = n) {
		if (tl == tr) {
			t[v].pb({-inf, inf});
			for (auto it : h[ver[tl]])
				t[v].pb({tin[it.F], it.S});
			t[v].pb({+inf, inf});
			sort(all(t[v]));
			p[v].resize(sz(t[v]));		
			s[v].resize(sz(t[v]));
			for (int i = 0; i < sz(t[v]); ++i) {
				p[v][i] = t[v][i].S;
				if (i) p[v][i] = min(p[v][i], p[v][i - 1]);
			}
			for (int i = sz(t[v]) - 1; i >= 0; --i) {
				s[v][i] = t[v][i].S;
				if (i != sz(t[v]) - 1) s[v][i] = min(s[v][i], s[v][i + 1]);
			}
			return;
		}
		int tm = tl + tr >> 1;
		build(v * 2, tl, tm);
		build(v * 2 + 1, tm + 1, tr);
		int i = 0, j = 0;
		t[v].pb({-inf, inf});
		while (i != sz(t[v * 2]) && j != sz(t[v * 2 + 1])) {
			if (t[v * 2][i].F < t[v * 2 + 1][j].F) {
				if (t[v * 2][i].S != inf)
					t[v].pb(t[v * 2][i]);
				++i;
			}
			else {
				if (t[v * 2 + 1][j].S != inf)
					t[v].pb(t[v * 2 + 1][j]);
				++j;
			}
		}
		while (i < sz(t[v * 2])) {
			if (t[v * 2][i].S != inf)
				t[v].pb(t[v * 2][i]);
			++i;
		}
		while (j < sz(t[v * 2 + 1])) {
			if (t[v * 2 + 1][j].S != inf)
				t[v].pb(t[v * 2 + 1][j]);
			++j;
		}
		t[v].pb({+inf, inf});
		p[v].resize(sz(t[v]));		
		s[v].resize(sz(t[v]));
		for (int i = 0; i < sz(t[v]); ++i) {
			p[v][i] = t[v][i].S;
			if (i) p[v][i] = min(p[v][i], p[v][i - 1]);
		}
		for (int i = sz(t[v]) - 1; i >= 0; --i) {
			s[v][i] = t[v][i].S;
			if (i != sz(t[v]) - 1) s[v][i] = min(s[v][i], s[v][i + 1]);
		}
	}
	
	int get(int l, int r, int v = 1, int tl = 1, int tr = n) {
		if (l <= tl && tr <= r) {
			int mn = inf;
			if (t[v].empty())
				return mn;
			for (auto it : t[v])
				if (it.F < l || r < it.F)
					mn = min(mn, it.S);
			return mn;
			int i = lb(all(t[v]), mp(l, -inf)) - t[v].begin() - 1;
			int j = ub(all(t[v]), mp(r, +inf)) - t[v].begin();
			return min(p[v][i], s[v][j]);
		}
		if (r < tl || tr < l)
			return inf;
		int tm = tl + tr >> 1;
		return min(get(l, r, v * 2, tl, tm), get(l, r, v * 2 + 1, tm + 1, tr));
	}
} t;

int main() {
	speed;
	cin >> n >> m;
	for (int i = 1; i <= n; ++i)
		p[i] = i, sz[i] = 1;
	for (int i = 1, a, b, c; i <= m; ++i) {
		cin >> a >> b >> c;
		e[i] = {{c, i}, {a, b}};
	}
	sort(e + 1, e + m + 1);
	for (int i = 1; i <= m; ++i) {
		if (unite(e[i].S.F, e[i].S.S)) {
			is[e[i].F.S] = 1;
		}
	}
	for (int i = 1; i <= m; ++i) {
		if (!is[e[i].F.S]) {
			h[e[i].S.F].pb({e[i].S.S, e[i].F.F});
			h[e[i].S.S].pb({e[i].S.F, e[i].F.F});
		}
		else {
			ans += e[i].F.F;
			g[e[i].S.F].pb({e[i].S.S, i});
			g[e[i].S.S].pb({e[i].S.F, i});
		}
	}
	dfs();
	t.build();
	for (int i = 2; i <= n; ++i) {
		int l = tin[i], r = tout[i];
		int mn = t.get(l, r);
		if (mn == inf)
			ret[e[id[i]].F.S] = -1;
		else
			ret[e[id[i]].F.S] = ans - e[id[i]].F.F + mn;
	}
	for (int i = 1; i <= m; ++i) {
		if (!is[i])
			ret[i] = ans;
		cout << ret[i] << '\n';
	}
}
accuracy: 0.8918918918918919
time_ms: 270
memory_kb: 225464
final_rank: 19

code_snippet: // competitive-verifier: PROBLEM https://onlinejudge.u-aizu.ac.jp/problems/2559
#include <iostream>
#include <vector>
/**
 * @brief 重み付きグラフ
 *
 * @tparam T 辺の重みの型
 */
template <class T>
struct Graph {
  private:
    struct _edge {
        constexpr _edge() : _from(), _to(), _weight() {}
        constexpr _edge(int from, int to, T weight) : _from(from), _to(to), _weight(weight) {}
        constexpr bool operator<(const _edge &rhs) const { return weight() < rhs.weight(); }
        constexpr bool operator>(const _edge &rhs) const { return rhs < *this; }
        constexpr int from() const { return _from; }
        constexpr int to() const { return _to; }
        constexpr T weight() const { return _weight; }
      private:
        int _from, _to;
        T _weight;
    };
  public:
    using edge_type = typename Graph<T>::_edge;
    Graph() : _size(), edges() {}
    Graph(int v) : _size(v), edges(v) {}
    const auto &operator[](int i) const { return edges[i]; }
    auto &operator[](int i) { return edges[i]; }
    const auto begin() const { return edges.begin(); }
    auto begin() { return edges.begin(); }
    const auto end() const { return edges.end(); }
    auto end() { return edges.end(); }
    constexpr int size() const { return _size; }
    void add_edge(const edge_type &e) { edges[e.from()].emplace_back(e); }
    void add_edge(int from, int to, T weight = T(1)) { edges[from].emplace_back(from, to, weight); }
    void add_edges(int from, int to, T weight = T(1)) {
        edges[from].emplace_back(from, to, weight);
        edges[to].emplace_back(to, from, weight);
    }
    void input_edge(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            T weight;
            std::cin >> from >> to >> weight;
            add_edge(from - base, to - base, weight);
        }
    }
    void input_edges(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            T weight;
            std::cin >> from >> to >> weight;
            add_edges(from - base, to - base, weight);
        }
    }
  private:
    int _size;
    std::vector<std::vector<edge_type>> edges;
};
template <>
struct Graph<void> {
  private:
    struct _edge {
        constexpr _edge() : _from(), _to() {}
        constexpr _edge(int from, int to) : _from(from), _to(to) {}
        constexpr int from() const { return _from; }
        constexpr int to() const { return _to; }
        constexpr int weight() const { return 1; }
        constexpr bool operator<(const _edge &rhs) const { return weight() < rhs.weight(); }
        constexpr bool operator>(const _edge &rhs) const { return rhs < *this; }
      private:
        int _from, _to;
    };
  public:
    using edge_type = typename Graph<void>::_edge;
    Graph() : _size(), edges() {}
    Graph(int v) : _size(v), edges(v) {}
    const auto &operator[](int i) const { return edges[i]; }
    auto &operator[](int i) { return edges[i]; }
    const auto begin() const { return edges.begin(); }
    auto begin() { return edges.begin(); }
    const auto end() const { return edges.end(); }
    auto end() { return edges.end(); }
    constexpr int size() const { return _size; }
    void add_edge(const edge_type &e) { edges[e.from()].emplace_back(e); }
    void add_edge(int from, int to) { edges[from].emplace_back(from, to); }
    void add_edges(int from, int to) {
        edges[from].emplace_back(from, to);
        edges[to].emplace_back(to, from);
    }
    void input_edge(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            std::cin >> from >> to;
            add_edge(from - base, to - base);
        }
    }
    void input_edges(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            std::cin >> from >> to;
            add_edges(from - base, to - base);
        }
    }
  private:
    int _size;
    std::vector<std::vector<edge_type>> edges;
};
#include <functional>
#include <utility>
/// @brief skew heap
/// @see http://hos.ac/blog/#blog0001
template <class T, class Comp = std::less<>>
struct skew_heap {
  private:
    struct _node {
        using pointer = _node *;
        pointer _left, _right;
        T _val;
        constexpr _node() : _left(), _right(), _val() {}
        constexpr _node(const T &val) : _left(), _right(), _val(val) {}
        constexpr _node(T &&val) : _left(), _right(), _val(std::move(val)) {}
        template <typename... Args>
        constexpr _node(Args &&...args) : _left(), _right(), _val(std::forward<Args>(args)...) {}
    };
  public:
    using value_type = T;
    using node_ptr = typename _node::pointer;
    constexpr skew_heap() : _root(), _comp() {}
    constexpr bool empty() const { return !_root; }
    constexpr T top() const { return _root->_val; }
    constexpr void push(const T &val) {
        auto node = new _node(val);
        _root = meld(_root, node);
    }
    constexpr void push(T &&val) {
        auto node = new _node(std::move(val));
        _root = meld(_root, node);
    }
    template <typename... Args>
    constexpr void emplace(Args &&...args) {
        auto node = new _node(std::forward<Args>(args)...);
        _root = meld(_root, node);
    }
    constexpr void pop() { _root = meld(_root->_left, _root->_right); }
    constexpr void meld(const skew_heap<T, Comp> &rhs) { _root = meld(_root, rhs._root); }
  private:
    node_ptr _root;
    Comp _comp;
    constexpr node_ptr meld(node_ptr a, node_ptr b) const {
        if (!a) return b;
        if (!b) return a;
        if (_comp(a->_val, b->_val)) std::swap(a, b);
        a->_right = meld(a->_right, b);
        std::swap(a->_left, a->_right);
        return a;
    }
};
#ifdef ATCODER
#pragma GCC target("sse4.2,avx512f,avx512dq,avx512ifma,avx512cd,avx512bw,avx512vl,bmi2")
#endif
#pragma GCC optimize("Ofast,fast-math,unroll-all-loops")
#include <bits/stdc++.h>
#ifndef ATCODER
#pragma GCC target("sse4.2,avx2,bmi2")
#endif
template <class T, class U>
constexpr bool chmax(T &a, const U &b) {
    return a < (T)b ? a = (T)b, true : false;
}
template <class T, class U>
constexpr bool chmin(T &a, const U &b) {
    return (T)b < a ? a = (T)b, true : false;
}
constexpr std::int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr double EPS = 1e-7;
constexpr double PI = 3.14159265358979323846;
#define FOR(i, m, n) for (int i = (m); i < int(n); ++i)
#define FORR(i, m, n) for (int i = (m)-1; i >= int(n); --i)
#define FORL(i, m, n) for (int64_t i = (m); i < int64_t(n); ++i)
#define rep(i, n) FOR (i, 0, n)
#define repn(i, n) FOR (i, 1, n + 1)
#define repr(i, n) FORR (i, n, 0)
#define repnr(i, n) FORR (i, n + 1, 1)
#define all(s) (s).begin(), (s).end()
struct Sonic {
    Sonic() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(20);
    }
    constexpr void operator()() const {}
} sonic;
using namespace std;
using ll = std::int64_t;
using ld = long double;
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    return is >> p.first >> p.second;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
    for (T &i : v) is >> i;
    return is;
}
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) os << (it == v.begin() ? "" : " ") << *it;
    return os;
}
template <class Head, class... Tail>
void co(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cout << head << '\n';
    else std::cout << head << ' ', co(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cerr << head << '\n';
    else std::cerr << head << ' ', ce(std::forward<Tail>(tail)...);
}
void Yes(bool is_correct = true) { std::cout << (is_correct ? "Yes\n" : "No\n"); }
void No(bool is_not_correct = true) { Yes(!is_not_correct); }
void YES(bool is_correct = true) { std::cout << (is_correct ? "YES\n" : "NO\n"); }
void NO(bool is_not_correct = true) { YES(!is_not_correct); }
void Takahashi(bool is_correct = true) { std::cout << (is_correct ? "Takahashi" : "Aoki") << '\n'; }
void Aoki(bool is_not_correct = true) { Takahashi(!is_not_correct); }
/**
 * @brief 素集合データ構造
 * @details Implement (union by size) + (path compression)
 * @see https://github.com/atcoder/ac-library/blob/master/atcoder/dsu.hpp
 */
struct union_find {
    union_find() = default;
    explicit union_find(int _n) : _rank(_n), data(_n, -1) {}
    const int &operator[](std::size_t x) const { return data[x]; }
    int &operator[](std::size_t x) { return data[x]; }
    int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
    int get_root(int x) { return root(x); }
    bool is_root(int x) const { return data[x] < 0; }
    bool same(int x, int y) { return root(x) == root(y); }
    bool is_same(int x, int y) { return same(x, y); }
    int rank() { return _rank; }
    int size(int x) { return -(data[root(x)]); }
    int get_size(int x) { return size(x); }
    std::vector<int> leaders() {
        std::vector<int> res;
        for (int i = 0; i < (int)data.size(); ++i) {
            if (is_root(i)) res.emplace_back(i);
        }
        return res;
    }
    bool unite(int x, int y) {
        x = root(x), y = root(y);
        if (x == y) return false;
        --_rank;
        if (data[x] > data[y]) std::swap(x, y);
        data[x] += data[y];
        data[y] = x;
        return true;
    }
    template <class F>
    bool unite(int x, int y, F f) {
        x = root(x), y = root(y);
        if (x != y) {
            if (data[x] > data[y]) std::swap(x, y);
            data[x] += data[y];
            data[y] = x;
        }
        f(x, y);
        return x != y;
    }
  private:
    int _rank;
    std::vector<int> data;
};
int main(void) {
    int n, m;
    std::cin >> n >> m;
    std::vector<std::tuple<int, int, int>> edges(m);
    for (auto &[u, v, w] : edges) std::cin >> u >> v >> w, --u, --v;
    std::vector<int> ord(m);
    std::iota(ord.begin(), ord.end(), 0);
    std::sort(ord.begin(), ord.end(), [&](int x, int y) {
        return std::get<2>(edges[x]) < std::get<2>(edges[y]);
    });
    std::int64_t sum = 0;
    union_find uf(n);
    std::vector<skew_heap<std::pair<int, int>, std::greater<>>> heap(n);
    Graph<int> g(n);
    std::vector<bool> used(m);
    for (auto x : ord) {
        auto [u, v, w] = edges[x];
        if (uf.same(u, v)) {
            heap[u].emplace(w, v);
            heap[v].emplace(w, u);
        } else {
            sum += w;
            uf.unite(u, v);
            g.add_edges(u, v, x);
            used[x] = true;
        }
    }
    if (uf.size(0) != n) {
        for (int i = 0; i < m; ++i) std::cout << -1 << '\n';
        return 0;
    }
    std::vector<std::int64_t> ans(m, -1);
    for (int i = 0; i < m; ++i) {
        if (!used[i])
            ans[i] = sum;
    }
    uf = union_find(n);
    auto dfs = [&](auto self, int x, int p) -> void {
        for (auto e : g[x]) {
            if (e.to() == p)
                continue;
            self(self, e.to(), x);
            while (!heap[e.to()].empty() && uf.same(e.to(), heap[e.to()].top().second))
                heap[e.to()].pop();
            if (!heap[e.to()].empty()) {
                auto [u, v, w] = edges[e.weight()];
                ans[e.weight()] = sum - w + heap[e.to()].top().first;
            }
            heap[x].meld(heap[e.to()]);
            uf.unite(x, e.to());
        }
    };
    dfs(dfs, 0, -1);
    for (int i = 0; i < m; ++i) std::cout << ans[i] << '\n';
    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 32184
final_rank: 1

code_snippet: #line 1 "2559.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/2559"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Template/IOSetting.hpp"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Template/TypeAlias.hpp"

#include <cstdint>
#include <cstddef>

namespace zawa {

using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;

using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;

using usize = std::size_t;

} // namespace zawa
#line 4 "/home/zawatin/compro/cp-documentation/Src/Template/IOSetting.hpp"

#include <iostream>
#include <iomanip>

namespace zawa {

void SetFastIO() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
}

void SetPrecision(u32 dig) {
    std::cout << std::fixed << std::setprecision(dig);
}

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/DataStructure/SparseTable/DualSparseTable.hpp"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Algebra/Monoid/MonoidConcept.hpp"

#include <concepts>

namespace zawa {

namespace Concept {

template <class T>
concept Monoid = requires {
    typename T::Element;
    { T::identity() } -> std::same_as<typename T::Element>;
    { T::operation(std::declval<typename T::Element>(), std::declval<typename T::Element>()) } -> std::same_as<typename T::Element>;
};

} // namespace

} // namespace zawa
#line 5 "/home/zawatin/compro/cp-documentation/Src/DataStructure/SparseTable/DualSparseTable.hpp"

#include <vector>
#include <cassert>

namespace zawa {

template <Concept::Monoid S>
class DualSparseTable {
public:
    using Value = typename S::Element;

    DualSparseTable() = default;
    
    DualSparseTable(const std::vector<Value>& A)
        : n_{A.size()}, L_(A.size() + 1), dat_{} {
        
        assert(A.size());
        for (u32 i{1} ; i < L_.size() ; i++) {
            L_[i] = L_[i - 1] + (i >> (L_[i - 1] + 1));
        }
        dat_ = std::vector(L_.back() + 1, std::vector(A.size(), S::identity()));
        dat_[0] = A;
    }

    void operation(u32 L, u32 R, const Value& v) {
        assert(L <= R and R <= size());
        if (L == R) {
            return;
        }
        else if (L + 1 == R) {
            dat_[0][L] = S::operation(dat_[0][L], v);
        }
        else {
            u32 now{L_[R - L]};
            dat_[now][L] = S::operation(dat_[now][L], v);
            dat_[now][R - (1 << now)] = S::operation(dat_[now][R - (1 << now)], v);
        }
    }

    constexpr usize size() const {
        return n_;
    }

    std::vector<Value> build() {
        assert(dat_.size() >= 2u);
        for (u32 i{static_cast<u32>(dat_.size()) - 2u} ; i + 1 < dat_.size() ; i--) {
            for (u32 j{} ; j + (1 << i) < size() ; j++) {
                dat_[i][j] = S::operation(dat_[i][j], dat_[i + 1][j]);
                dat_[i][j + (1 << i)] = S::operation(dat_[i][j + (1 << i)], dat_[i + 1][j]);
            }
        }
        return dat_[0];
    }

private:
    
    usize n_{};
    std::vector<u32> L_;
    std::vector<std::vector<Value>> dat_{};
};

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"

#line 4 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"

#include <algorithm>
#line 7 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"
#include <numeric>
#line 9 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"

namespace zawa {

class DisjointSetUnion {
public:
    DisjointSetUnion() = default;

    DisjointSetUnion(usize n) : n_{n}, comps_{n}, data_(n, -1) {
        data_.shrink_to_fit();
    }
    
    u32 leader(u32 v) {
        return data_[v] < 0 ? v : static_cast<u32>(data_[v] = leader(data_[v]));
    }

    bool same(u32 u, u32 v) {
        return leader(u) == leader(v);
    }

    bool merge(u32 u, u32 v) {
        assert(u < n_);
        assert(v < n_);
        u = leader(u);
        v = leader(v);
        if (u == v) return false;
        comps_--;
        if (data_[u] > data_[v]) std::swap(u, v);
        data_[u] += data_[v];
        data_[v] = u;
        return true;
    }

    inline usize size() const noexcept {
        return n_;
    }

    usize size(u32 v) {
        assert(v < n_);
        return static_cast<usize>(-data_[leader(v)]);
    }

    inline usize components() const noexcept {
        return comps_;
    }

    std::vector<std::vector<u32>> enumerate() {
        std::vector<std::vector<u32>> res(n_);
        for (u32 v{} ; v < n_ ; v++) {
            res[leader(v)].push_back(v);
        }
        res.erase(std::remove_if(res.begin(), res.end(),
                    [](const auto& arr) -> bool { return arr.empty(); }), res.end());
        return res;
    }

private:
    usize n_{}, comps_{};
    std::vector<i32> data_;
};

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"

#line 4 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"

#line 7 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"
#include <cmath>
#include <limits>
#include <utility>
#line 11 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"

namespace zawa {

template <class V>
class HeavyLightDecomposition {
public:

    static constexpr V Invalid() noexcept {
        return INVALID;
    }

    HeavyLightDecomposition() = default;

    HeavyLightDecomposition(std::vector<std::vector<V>> T, V root = 0u) 
        : n_{T.size()}, par_(n_), top_(n_), idx_(n_), 
        inv_(n_), size_(n_, usize{1}), dep_(n_) {

            auto dfs1{[&](auto dfs, V v, V p, usize d) -> usize {
                par_[v] = p;
                dep_[v] = d;
                if (p != INVALID) {
                    for (u32 i{} ; i + 1 < T[v].size() ; i++) if (T[v][i] == p) {
                        std::swap(T[v][i], T[v].back());
                        break;
                    }
                    assert(T[v].back() == p);
                    T[v].pop_back();
                }
                for (V x : T[v]) {
                    size_[v] += dfs(dfs, x, v, d + 1);
                }
                for (u32 i{1} ; i < T[v].size() ; i++) if (size_[T[v][0]] < size_[T[v][i]]) {
                    std::swap(T[v][0], T[v][i]);
                }
                return size_[v];
            }};

            auto dfs2{[&](auto dfs, V v, V idx, V top) -> V {
                idx_[v] = idx++;
                inv_[idx_[v]] = v;
                top_[v] = top;
                if (T[v].size()) {
                    idx = dfs(dfs, T[v][0], idx, top);
                    for (u32 i{1} ; i < T[v].size() ; i++) {
                        idx = dfs(dfs, T[v][i], idx, T[v][i]);
                    }
                }
                return idx;
            }};

            dfs1(dfs1, root, INVALID, 0u);
            dfs2(dfs2, root, 0u, root);
        }

    inline usize size() const noexcept {
        return n_;
    }

    usize size(V v) const noexcept {
        assert(v < (V)size());
        return size_[v];
    }

    usize depth(V v) const noexcept {
        assert(v < (V)size());
        return dep_[v];
    }

    V parent(V v) const noexcept {
        assert(v < (V)size());
        return par_[v];
    }

    V index(V v) const noexcept {
        assert(v < (V)size());
        return idx_[v];
    }

    V operator[](V v) const noexcept {
        assert(v < (V)size());
        return idx_[v];
    }

    std::vector<std::pair<V, V>> decomp(V s, V t) const {
        assert(s < (V)size());
        assert(t < (V)size());
        std::vector<std::pair<V, V>> res, ser;
        while (top_[s] != top_[t]) {
            if (dep_[top_[s]] >= dep_[top_[t]]) {
                res.emplace_back(s, top_[s]);
                s = top_[s];
                if (par_[s] != INVALID) s = par_[s];
            }
            else {
                ser.emplace_back(top_[t], t);
                t = top_[t];
                if (par_[t] != INVALID) t = par_[t];
            }
        }
        res.emplace_back(s, t);
        std::reverse(ser.begin(), ser.end());
        res.insert(res.end(), ser.begin(), ser.end()); 
        return res;
    }

    std::vector<std::pair<V, V>> operator()(V s, V t) const {
        return decomp(s, t);
    }

    V lca(V u, V v) const {
        assert(u < (V)size());
        assert(v < (V)size());
        while (top_[u] != top_[v]) {
            if (dep_[top_[u]] >= dep_[top_[v]]) {
                u = top_[u];
                if (par_[u] != INVALID) u = par_[u];
            }
            else {
                v = top_[v];
                if (par_[v] != INVALID) v = par_[v];
            }
        }
        return (dep_[u] <= dep_[v] ? u : v);
    }

    // pはvの祖先か？
    bool isAncestor(V v, V p) {
        assert(v < size());
        assert(p < size());
        if (dep_[v] < dep_[p]) return false;
        while (v != INVALID and top_[v] != top_[p]) {
            v = par_[top_[v]];
        }
        return v != INVALID;
    }

    V levelAncestor(V v, usize step) const {
        assert(v < (V)size());
        if (step > dep_[v]) return INVALID;
        while (true) {
            usize dist{dep_[v] - dep_[top_[v]]};
            if (dist >= step) break;
            step -= dist + 1;
            v = par_[top_[v]];
        }
        step = (dep_[v] - dep_[top_[v]]) - step;
        return inv_[idx_[top_[v]] + step];
    }

    V jump(V s, V t, usize step) const {
        assert(s < (V)size());
        assert(t < (V)size());
        V uu{INVALID}, vv{INVALID};
        usize d{};
        for (auto [u, v] : decomp(s, t)) {
            usize dist{std::max(dep_[u], dep_[v]) - std::min(dep_[u], dep_[v])};
            if (dist >= step) {
                uu = u;
                vv = v;
                d = dist;
                break;
            }
            step -= dist + 1;
        }
        if (uu == INVALID) return INVALID;
        if (dep_[uu] <= dep_[vv]) {
            return inv_[idx_[uu] + step];
        }
        else {
            return inv_[idx_[vv] + (d - step)];
        }
    }

    usize distance(V s, V t) const {
        assert(s < (V)size());
        assert(t < (V)size());
        usize res{};
        for (auto [u, v] : decomp(s, t)) {
            if (dep_[u] > dep_[v]) std::swap(u, v);
            res += dep_[v] - dep_[u];
        }
        return res;
    }

private:
    static constexpr V INVALID{static_cast<V>(-1)};
    usize n_{};
    std::vector<V> par_{}, top_{}, idx_{}, inv_{};
    std::vector<usize> size_{}, dep_{};
};

} // namespace zawa
#line 7 "2559.test.cpp"

#line 10 "2559.test.cpp"
#include <tuple>
#line 13 "2559.test.cpp"

using namespace zawa;

struct MIN {
    using Element = int;
    static Element identity() {
        return (int)2e9;
    }
    static Element operation(Element L, Element R) {
        return std::min(L, R);
    }
};

int main() {
    SetFastIO();

    int N, M;
    std::cin >> N >> M;
    std::vector<std::tuple<int, int, int, int>> E(M);
    for (int i{} ; auto& [w, a, b, id] : E) {
        std::cin >> a >> b >> w;
        a--; b--;
        id = i++;
    }
    std::sort(E.begin(), E.end());
    DisjointSetUnion dsu(N);  
    std::vector<int> id(M, -1);
    int use_edge{};
    long long base{};
    for (auto [w, a, b, i] : E) {
        if (dsu.same(a, b)) continue;
        base += w;
        dsu.merge(a, b);
        id[i] = N + use_edge++;
    }
    assert(use_edge <= N - 1);
    if (use_edge < N - 1) {
        for (int i{} ; i < M ; i++) std::cout << -1 << '\n';
        return 0;
    }
    std::vector<std::vector<int>> T(N + N - 1);
    for (auto [_, a, b, i] : E) if (id[i] != -1) {
        T[a].push_back(id[i]);
        T[id[i]].push_back(a);
        // AddEdge(T, a, id[i]);
        T[b].push_back(id[i]);
        T[id[i]].push_back(b);
        // AddEdge(T, b, id[i]);
    }
    HeavyLightDecomposition hld{T};
    const int INF{MIN::identity()};
    DualSparseTable<MIN> spt{std::vector<int>(N + N - 1, INF)};
    for (auto [w, a, b, i] : E) if (id[i] == -1) {
        for (auto [l, r] : hld(a, b)) {
            l = hld[l];
            r = hld[r];
            if (l > r) std::swap(l, r);
            spt.operation(l, r + 1, w);
        }
    }
    auto prod{spt.build()};
    std::vector<long long> ans(M, -1LL);
    for (auto [w, a, b, i] : E) {
        if (id[i] == -1) ans[i] = base;
        else {
            int find{prod[hld[id[i]]]};
            ans[i] = (find == INF ? -1LL : base - w + find);
        }
    }
    for (int i{} ; i < M ; i++) {
        std::cout << ans[i] << '\n';
    }
}
accuracy: 1
time_ms: 100
memory_kb: 64896
final_rank: 4

code_snippet: #line 1 "2559.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/2559"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Template/IOSetting.hpp"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Template/TypeAlias.hpp"

#include <cstdint>
#include <cstddef>

namespace zawa {

using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;

using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;

using usize = std::size_t;

} // namespace zawa
#line 4 "/home/zawatin/compro/cp-documentation/Src/Template/IOSetting.hpp"

#include <iostream>
#include <iomanip>

namespace zawa {

void SetFastIO() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
}

void SetPrecision(u32 dig) {
    std::cout << std::fixed << std::setprecision(dig);
}

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/DataStructure/SparseTable/DualSparseTable.hpp"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Algebra/Monoid/MonoidConcept.hpp"

#include <concepts>

namespace zawa {

namespace Concept {

template <class T>
concept Monoid = requires {
    typename T::Element;
    { T::identity() } -> std::same_as<typename T::Element>;
    { T::operation(std::declval<typename T::Element>(), std::declval<typename T::Element>()) } -> std::same_as<typename T::Element>;
};

} // namespace

} // namespace zawa
#line 5 "/home/zawatin/compro/cp-documentation/Src/DataStructure/SparseTable/DualSparseTable.hpp"

#include <vector>
#include <cassert>

namespace zawa {

template <Concept::Monoid S>
class DualSparseTable {
public:
    using Value = typename S::Element;

    DualSparseTable() = default;
    
    DualSparseTable(const std::vector<Value>& A)
        : n_{A.size()}, L_(A.size() + 1), dat_{} {
        
        assert(A.size());
        for (u32 i{1} ; i < L_.size() ; i++) {
            L_[i] = L_[i - 1] + (i >> (L_[i - 1] + 1));
        }
        dat_ = std::vector(L_.back() + 1, std::vector(A.size(), S::identity()));
        dat_[0] = A;
    }

    void operation(u32 L, u32 R, const Value& v) {
        assert(L <= R and R <= size());
        if (L == R) {
            return;
        }
        else if (L + 1 == R) {
            dat_[0][L] = S::operation(dat_[0][L], v);
        }
        else {
            u32 now{L_[R - L]};
            dat_[now][L] = S::operation(dat_[now][L], v);
            dat_[now][R - (1 << now)] = S::operation(dat_[now][R - (1 << now)], v);
        }
    }

    constexpr usize size() const {
        return n_;
    }

    std::vector<Value> build() {
        assert(dat_.size() >= 2u);
        for (u32 i{static_cast<u32>(dat_.size()) - 2u} ; i + 1 < dat_.size() ; i--) {
            for (u32 j{} ; j + (1 << i) < size() ; j++) {
                dat_[i][j] = S::operation(dat_[i][j], dat_[i + 1][j]);
                dat_[i][j + (1 << i)] = S::operation(dat_[i][j + (1 << i)], dat_[i + 1][j]);
            }
        }
        return dat_[0];
    }

private:
    
    usize n_{};
    std::vector<u32> L_;
    std::vector<std::vector<Value>> dat_{};
};

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"

#line 4 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"

#include <algorithm>
#line 7 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"
#include <numeric>
#line 9 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"

namespace zawa {

class DisjointSetUnion {
public:
    DisjointSetUnion() = default;

    DisjointSetUnion(usize n) : n_{n}, data_(n, -1) {
        data_.shrink_to_fit();
    }
    
    u32 leader(u32 v) {
        return data_[v] < 0 ? v : static_cast<u32>(data_[v] = leader(data_[v]));
    }

    bool same(u32 u, u32 v) {
        return leader(u) == leader(v);
    }

    bool merge(u32 u, u32 v) {
        assert(u < n_);
        assert(v < n_);
        u = leader(u);
        v = leader(v);
        if (u == v) return false;
        if (data_[u] > data_[v]) std::swap(u, v);
        data_[u] += data_[v];
        data_[v] = u;
        return true;
    }

    inline usize size() const noexcept {
        return n_;
    }

    usize size(u32 v) {
        assert(v < n_);
        return static_cast<usize>(-data_[leader(v)]);
    }

    std::vector<std::vector<u32>> enumerate() {
        std::vector<std::vector<u32>> res(n_);
        for (u32 v{} ; v < n_ ; v++) {
            res[leader(v)].push_back(v);
        }
        res.erase(std::remove_if(res.begin(), res.end(),
                    [](const auto& arr) -> bool { return arr.empty(); }), res.end());
        return res;
    }

private:
    usize n_{};
    std::vector<i32> data_;
};

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"

#line 4 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"

#line 7 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"
#include <cmath>
#include <limits>
#include <utility>
#line 11 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"

namespace zawa {

template <class V>
class HeavyLightDecomposition {
public:

    static constexpr V Invalid() noexcept {
        return INVALID;
    }

    HeavyLightDecomposition() = default;

    HeavyLightDecomposition(std::vector<std::vector<V>> T, V root = 0u) 
        : n_{T.size()}, par_(n_), top_(n_), idx_(n_), 
        inv_(n_), size_(n_, usize{1}), dep_(n_) {

            auto dfs1{[&](auto dfs, V v, V p, usize d) -> usize {
                par_[v] = p;
                dep_[v] = d;
                if (p != INVALID) {
                    for (u32 i{} ; i + 1 < T[v].size() ; i++) if (T[v][i] == p) {
                        std::swap(T[v][i], T[v].back());
                        break;
                    }
                    assert(T[v].back() == p);
                    T[v].pop_back();
                }
                for (V x : T[v]) {
                    size_[v] += dfs(dfs, x, v, d + 1);
                }
                for (u32 i{1} ; i < T[v].size() ; i++) if (size_[T[v][0]] < size_[T[v][i]]) {
                    std::swap(T[v][0], T[v][i]);
                }
                return size_[v];
            }};

            auto dfs2{[&](auto dfs, V v, V idx, V top) -> V {
                idx_[v] = idx++;
                inv_[idx_[v]] = v;
                top_[v] = top;
                if (T[v].size()) {
                    idx = dfs(dfs, T[v][0], idx, top);
                    for (u32 i{1} ; i < T[v].size() ; i++) {
                        idx = dfs(dfs, T[v][i], idx, T[v][i]);
                    }
                }
                return idx;
            }};

            dfs1(dfs1, root, INVALID, 0u);
            dfs2(dfs2, root, 0u, root);
        }

    inline usize size() const noexcept {
        return n_;
    }

    usize size(V v) const noexcept {
        assert(v < (V)size());
        return size_[v];
    }

    usize depth(V v) const noexcept {
        assert(v < (V)size());
        return dep_[v];
    }

    V parent(V v) const noexcept {
        assert(v < (V)size());
        return par_[v];
    }

    V index(V v) const noexcept {
        assert(v < (V)size());
        return idx_[v];
    }

    V operator[](V v) const noexcept {
        assert(v < (V)size());
        return idx_[v];
    }

    std::vector<std::pair<V, V>> decomp(V s, V t) const {
        assert(s < (V)size());
        assert(t < (V)size());
        std::vector<std::pair<V, V>> res, ser;
        while (top_[s] != top_[t]) {
            if (dep_[top_[s]] >= dep_[top_[t]]) {
                res.emplace_back(s, top_[s]);
                s = top_[s];
                if (par_[s] != INVALID) s = par_[s];
            }
            else {
                ser.emplace_back(top_[t], t);
                t = top_[t];
                if (par_[t] != INVALID) t = par_[t];
            }
        }
        res.emplace_back(s, t);
        std::reverse(ser.begin(), ser.end());
        res.insert(res.end(), ser.begin(), ser.end()); 
        return res;
    }

    std::vector<std::pair<V, V>> operator()(V s, V t) const {
        return decomp(s, t);
    }

    V lca(V u, V v) const {
        assert(u < (V)size());
        assert(v < (V)size());
        while (top_[u] != top_[v]) {
            if (dep_[top_[u]] >= dep_[top_[v]]) {
                u = top_[u];
                if (par_[u] != INVALID) u = par_[u];
            }
            else {
                v = top_[v];
                if (par_[v] != INVALID) v = par_[v];
            }
        }
        return (dep_[u] <= dep_[v] ? u : v);
    }

    // pはvの祖先か？
    bool isAncestor(V v, V p) {
        assert(v < size());
        assert(p < size());
        if (dep_[v] < dep_[p]) return false;
        while (v != INVALID and top_[v] != top_[p]) {
            v = par_[top_[v]];
        }
        return v != INVALID;
    }

    V levelAncestor(V v, usize step) const {
        assert(v < (V)size());
        if (step > dep_[v]) return INVALID;
        while (true) {
            usize dist{dep_[v] - dep_[top_[v]]};
            if (dist >= step) break;
            step -= dist + 1;
            v = par_[top_[v]];
        }
        step = (dep_[v] - dep_[top_[v]]) - step;
        return inv_[idx_[top_[v]] + step];
    }

    V jump(V s, V t, usize step) const {
        assert(s < (V)size());
        assert(t < (V)size());
        V uu{INVALID}, vv{INVALID};
        usize d{};
        for (auto [u, v] : decomp(s, t)) {
            usize dist{std::max(dep_[u], dep_[v]) - std::min(dep_[u], dep_[v])};
            if (dist >= step) {
                uu = u;
                vv = v;
                d = dist;
                break;
            }
            step -= dist + 1;
        }
        if (uu == INVALID) return INVALID;
        if (dep_[uu] <= dep_[vv]) {
            return inv_[idx_[uu] + step];
        }
        else {
            return inv_[idx_[vv] + (d - step)];
        }
    }

    usize distance(V s, V t) const {
        assert(s < (V)size());
        assert(t < (V)size());
        usize res{};
        for (auto [u, v] : decomp(s, t)) {
            if (dep_[u] > dep_[v]) std::swap(u, v);
            res += dep_[v] - dep_[u];
        }
        return res;
    }

private:
    static constexpr V INVALID{static_cast<V>(-1)};
    usize n_{};
    std::vector<V> par_{}, top_{}, idx_{}, inv_{};
    std::vector<usize> size_{}, dep_{};
};

} // namespace zawa
#line 7 "2559.test.cpp"

#line 10 "2559.test.cpp"
#include <tuple>
#line 13 "2559.test.cpp"

using namespace zawa;

struct MIN {
    using Element = int;
    static Element identity() {
        return (int)2e9;
    }
    static Element operation(Element L, Element R) {
        return std::min(L, R);
    }
};

int main() {
    SetFastIO();

    int N, M;
    std::cin >> N >> M;
    std::vector<std::tuple<int, int, int, int>> E(M);
    for (int i{} ; auto& [w, a, b, id] : E) {
        std::cin >> a >> b >> w;
        a--; b--;
        id = i++;
    }
    std::sort(E.begin(), E.end());
    DisjointSetUnion dsu(N);  
    std::vector<int> id(M, -1);
    int use_edge{};
    long long base{};
    for (auto [w, a, b, i] : E) {
        if (dsu.same(a, b)) continue;
        base += w;
        dsu.merge(a, b);
        id[i] = N + use_edge++;
    }
    assert(use_edge <= N - 1);
    if (use_edge < N - 1) {
        for (int i{} ; i < M ; i++) std::cout << -1 << '\n';
        return 0;
    }
    std::vector<std::vector<int>> T(N + N - 1);
    for (auto [_, a, b, i] : E) if (id[i] != -1) {
        T[a].push_back(id[i]);
        T[id[i]].push_back(a);
        // AddEdge(T, a, id[i]);
        T[b].push_back(id[i]);
        T[id[i]].push_back(b);
        // AddEdge(T, b, id[i]);
    }
    HeavyLightDecomposition hld{T};
    const int INF{MIN::identity()};
    DualSparseTable<MIN> spt{std::vector<int>(N + N - 1, INF)};
    for (auto [w, a, b, i] : E) if (id[i] == -1) {
        for (auto [l, r] : hld(a, b)) {
            l = hld[l];
            r = hld[r];
            if (l > r) std::swap(l, r);
            spt.operation(l, r + 1, w);
        }
    }
    auto prod{spt.build()};
    std::vector<long long> ans(M, -1LL);
    for (auto [w, a, b, i] : E) {
        if (id[i] == -1) ans[i] = base;
        else {
            int find{prod[hld[id[i]]]};
            ans[i] = (find == INF ? -1LL : base - w + find);
        }
    }
    for (int i{} ; i < M ; i++) {
        std::cout << ans[i] << '\n';
    }
}
accuracy: 1
time_ms: 100
memory_kb: 64896
final_rank: 4

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

struct UnionFind{
    vector<int> par; int n;
    UnionFind(){}
    UnionFind(int _n):par(_n,-1),n(_n){}
    int root(int x){return par[x]<0?x:par[x]=root(par[x]);}
    bool same(int x,int y){return root(x)==root(y);}
    int size(int x){return -par[root(x)];}
    bool unite(int x,int y){
        x=root(x),y=root(y); if(x==y)return false;
        if(size(x)>size(y))swap(x,y);
        par[y]+=par[x]; par[x]=y; n--; return true;
    }
};

/**
 * @brief Union Find
 */

struct HLD{
    using P=pair<int,int>;
    vector<vector<int>> g; vector<int> sz,in,out,rev,hs,par,dist;
    void dfs(int v,int p){
        par[v]=p; sz[v]=1;
        if(p!=-1)dist[v]=dist[p]+1;
        if(!g[v].empty() and g[v][0]==p)swap(g[v][0],g[v].back());
        for(auto& to:g[v])if(to!=p){
           dfs(to,v); sz[v]+=sz[to];
           if(sz[g[v][0]]<sz[to])swap(g[v][0],to);
        }
    }
    void dfs2(int v,int p,int& k){
        in[v]=k++; rev[in[v]]=v;
        for(auto& to:g[v])if(to!=p){
            hs[to]=(g[v][0]==to?hs[v]:to);
            dfs2(to,v,k);
        }
        out[v]=k;
    }
    HLD(int _n):g(_n),sz(_n),in(_n),out(_n),rev(_n),hs(_n),par(_n),dist(_n){}
    void add_edge(int u,int v){
        g[u].emplace_back(v); g[v].emplace_back(u);
    }
    void run(int rt=0){dfs(rt,-1); hs[rt]=rt; int k=0; dfs2(rt,-1,k);}
    int lca(int u,int v){
        for(;;v=par[hs[v]]){
            if(in[u]>in[v])swap(u,v);
            if(hs[u]==hs[v])return u;
        }
    }
    vector<P> get(int u,int p,bool es=0){
        assert(in[p]<=in[u] and out[u]<=out[p]);
        vector<P> res;
        while(hs[u]!=hs[p]){
            res.push_back({in[hs[u]],in[u]+1});
            u=par[hs[u]];
        }
        res.push_back({in[p]+es,in[u]+1});
        return res;
    }
    int jump(int u,int v,int k){
        if(k<0)return -1;
        int g=lca(u,v);
        int d0=dist[u]+dist[v]-dist[g]*2;
        if(d0<k)return -1;
        int st=u;
        if(dist[u]-dist[g]<k)st=v,k=d0-k;
        for(;;){
            int to=hs[st];
            if(in[st]-k>=in[to])return rev[in[st]-k];
            k-=in[st]-in[to]+1; st=par[to];
        }
    }
};

/**
 * @brief Heavy Light Decomposition
 */

template <typename M, typename N, M (*f)(M, M), M (*g)(M, N), N (*h)(N, N),
          M (*m1)(), N (*n1)()>
class LazySegmentTree {
    int n, sz, height;
    vector<M> data;
    vector<N> lazy;
    void update(int k) {
        data[k] = f(data[k * 2], data[k * 2 + 1]);
    }
    void apply(int k, N x) {
        data[k] = g(data[k], x);
        if (k < sz)
            lazy[k] = h(lazy[k], x);
    }
    void down(int k) {
        apply(k * 2, lazy[k]);
        apply(k * 2 + 1, lazy[k]);
        lazy[k] = n1();
    }

  public:
    LazySegmentTree(int n = 0) : LazySegmentTree(vector<M>(n, m1())) {}
    LazySegmentTree(const vector<M> &a) : n(SZ(a)) {
        sz = 1, height = 0;
        while (sz < (int)a.size())
            sz <<= 1, height++;
        data.assign(2 * sz, m1());
        lazy.assign(sz, n1());
        rep(i, 0, a.size()) data[sz + i] = a[i];
        for (int i = sz - 1; i; i--)
            update(i);
    }
    M operator[](int k) const {
        k += sz;
        rrep(i, 1, height + 1) down(k >> i);
        return data[k];
    }
    vector<M> get() {
        rep(k, 1, sz) down(k);
        return {data.begin() + sz, data.begin() + sz + n};
    }
    void set(int k, M x) {
        k += sz;
        for (int i = height; i; i--)
            down(k >> i);
        data[k] = x;
        for (int i = 1; i <= height; i++)
            update(k >> i);
    }
    void update(int L, int R, N x) {
        if (L >= R)
            return;
        L += sz, R += sz;
        for (int i = height; i; i--) {
            if (((L >> i) << i) != L)
                down(L >> i);
            if (((R >> i) << i) != R)
                down((R - 1) >> i);
        }
        int lb = L, rb = R;
        while (L < R) {
            if (L & 1)
                apply(L++, x);
            if (R & 1)
                apply(--R, x);
            L >>= 1;
            R >>= 1;
        }
        L = lb, R = rb;
        for (int i = 1; i <= height; i++) {
            if (((L >> i) << i) != L)
                update(L >> i);
            if (((R >> i) << i) != R)
                update((R - 1) >> i);
        }
    }
    M query(int L, int R) {
        if (L >= R)
            return m1();
        L += sz, R += sz;
        for (int i = height; i; i--) {
            if (((L >> i) << i) != L)
                down(L >> i);
            if (((R >> i) << i) != R)
                down((R - 1) >> i);
        }
        M lb = m1(), rb = m1();
        while (L < R) {
            if (L & 1)
                lb = f(lb, data[L++]);
            if (R & 1)
                rb = f(data[--R], rb);
            L >>= 1;
            R >>= 1;
        }
        return f(lb, rb);
    }
    template <class F> int max_right(int L, F ch) {
        if (L == n)
            return n;
        L += sz;
        rrep(i, 1, height + 1) down(L >> i);
        M sum = m1();
        do {
            while (L % 2 == 0)
                L >>= 1;
            if (!ch(f(sum, data[L]))) {
                while (L < sz) {
                    down(L);
                    L <<= 1;
                    if (ch(f(sum, data[L])))
                        sum = f(sum, data[L++]);
                }
                return L - sz;
            }
            sum = f(sum, data[L++]);
        } while ((L & -L) != L);
        return n;
    }
    template <class F> int min_left(int R, F ch) {
        if (R == 0)
            return 0;
        R += sz;
        rrep(i, 1, height + 1) down((R - 1) >> i);
        M sum = m1();
        do {
            R--;
            while (R > 1 and (R & 1))
                R >>= 1;
            if (!ch(f(data[R], sum))) {
                while (R < sz) {
                    down(R);
                    R = (R * 2 + 1);
                    if (ch(f(data[R], sum))) {
                        sum = f(data[R--], sum);
                    }
                }
                return R + 1 - sz;
            }
            sum = f(data[R], sum);
        } while ((R & -R) != R);
        return 0;
    }
};

/**
 * @brief Lazy Segment Tree
 */

ll f(ll A, ll B) {return min(A,B);}
ll g(ll A, ll B) {return min(A,B);}
ll h(ll A, ll B) {return min(A,B);}
ll e1() {return INF;}
ll e2() {return INF;}

int main() {
    int N, M;
    cin >> N >> M;
    vector<int> A(M), B(M);
    vector<ll> C(M);
    rep(i,0,M) {
        cin >> A[i] >> B[i] >> C[i];
        A[i]--, B[i]--;
    }
    vector<bool> used(M,false);
    ll MST = 0;
    vector<int> ord(M);
    iota(ALL(ord),0);
    sort(ALL(ord),[&](int i, int j){return C[i] < C[j];});
    UnionFind UF(N);
    for (int i : ord) {
        if (UF.unite(A[i],B[i])) {
            MST += C[i];
            used[i] = true;
        }
    }
    if (UF.n != 1) {
        rep(i,0,M) {
            cout << -1 << endl;
        }
        return 0;
    }
    HLD G(N);
    rep(i,0,M) if (used[i]) G.add_edge(A[i],B[i]);
    G.run();
    vector<ll> ANS(M);
    LazySegmentTree<ll,ll,f,g,h,e1,e2> Seg(N);
    rep(i,0,M) {
        if (used[i]) continue;
        ANS[i] = MST;
        int U = A[i], V = B[i];
        int lca = G.lca(U,V);
        auto ps = G.get(U,lca,1);
        for (auto [L,R] : ps) Seg.update(L,R,C[i]);
        ps = G.get(V,lca,1);
        for (auto [L,R] : ps) Seg.update(L,R,C[i]);
    }
    rep(i,0,M) {
        if (!used[i]) continue;
        int U = A[i], V = B[i];
        int lca = G.lca(U,V);
        int W = U + V - lca;
        ll Ret = Seg.query(G.in[W], G.in[W]+1);
        if (Ret == INF) ANS[i] = -1;
        else ANS[i] = MST - C[i] + Ret;
    }
    rep(i,0,M) cout << ANS[i] << endl;
}
accuracy: 1
time_ms: 430
memory_kb: 27168
final_rank: 17

code_snippet: #line 1 "2559.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/2559"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Template/IOSetting.hpp"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Template/TypeAlias.hpp"

#include <cstdint>
#include <cstddef>

namespace zawa {

using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;

using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;

using usize = std::size_t;

} // namespace zawa
#line 4 "/home/zawatin/compro/cp-documentation/Src/Template/IOSetting.hpp"

#include <iostream>
#include <iomanip>

namespace zawa {

void SetFastIO() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
}

void SetPrecision(u32 dig) {
    std::cout << std::fixed << std::setprecision(dig);
}

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/DataStructure/SparseTable/DualSparseTable.hpp"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Algebra/Monoid/MonoidConcept.hpp"

#include <concepts>

namespace zawa {

namespace Concept {

template <class T>
concept Monoid = requires {
    typename T::Element;
    { T::identity() } -> std::same_as<typename T::Element>;
    { T::operation(std::declval<typename T::Element>(), std::declval<typename T::Element>()) } -> std::same_as<typename T::Element>;
};

} // namespace

} // namespace zawa
#line 5 "/home/zawatin/compro/cp-documentation/Src/DataStructure/SparseTable/DualSparseTable.hpp"

#include <vector>
#include <cassert>

namespace zawa {

template <Concept::Monoid S>
class DualSparseTable {
public:
    using Value = typename S::Element;

    DualSparseTable() = default;
    
    DualSparseTable(const std::vector<Value>& A)
        : n_{A.size()}, L_(A.size() + 1), dat_{} {
        
        assert(A.size());
        for (u32 i{1} ; i < L_.size() ; i++) {
            L_[i] = L_[i - 1] + (i >> (L_[i - 1] + 1));
        }
        dat_ = std::vector(L_.back() + 1, std::vector(A.size(), S::identity()));
        dat_[0] = A;
    }

    void operation(u32 L, u32 R, const Value& v) {
        assert(L <= R and R <= size());
        if (L == R) {
            return;
        }
        else if (L + 1 == R) {
            dat_[0][L] = S::operation(dat_[0][L], v);
        }
        else {
            u32 now{L_[R - L]};
            dat_[now][L] = S::operation(dat_[now][L], v);
            dat_[now][R - (1 << now)] = S::operation(dat_[now][R - (1 << now)], v);
        }
    }

    constexpr usize size() const {
        return n_;
    }

    std::vector<Value> build() {
        assert(dat_.size() >= 2u);
        for (u32 i{static_cast<u32>(dat_.size()) - 2u} ; i + 1 < dat_.size() ; i--) {
            for (u32 j{} ; j + (1 << i) < size() ; j++) {
                dat_[i][j] = S::operation(dat_[i][j], dat_[i + 1][j]);
                dat_[i][j + (1 << i)] = S::operation(dat_[i][j + (1 << i)], dat_[i + 1][j]);
            }
        }
        return dat_[0];
    }

private:
    
    usize n_{};
    std::vector<u32> L_;
    std::vector<std::vector<Value>> dat_{};
};

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"

#line 4 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"

#include <algorithm>
#line 7 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"
#include <numeric>
#line 9 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"

namespace zawa {

class DisjointSetUnion {
public:
    DisjointSetUnion() = default;

    DisjointSetUnion(usize n) : n_{n}, data_(n, -1) {
        data_.shrink_to_fit();
    }
    
    u32 leader(u32 v) {
        return data_[v] < 0 ? v : static_cast<u32>(data_[v] = leader(data_[v]));
    }

    bool same(u32 u, u32 v) {
        return leader(u) == leader(v);
    }

    bool merge(u32 u, u32 v) {
        assert(u < n_);
        assert(v < n_);
        u = leader(u);
        v = leader(v);
        if (u == v) return false;
        if (data_[u] > data_[v]) std::swap(u, v);
        data_[u] += data_[v];
        data_[v] = u;
        return true;
    }

    inline usize size() const noexcept {
        return n_;
    }

    usize size(u32 v) {
        assert(v < n_);
        return static_cast<usize>(-data_[leader(v)]);
    }

    std::vector<std::vector<u32>> enumerate() {
        std::vector<std::vector<u32>> res(n_);
        for (u32 v{} ; v < n_ ; v++) {
            res[leader(v)].push_back(v);
        }
        res.erase(std::remove_if(res.begin(), res.end(),
                    [](const auto& arr) -> bool { return arr.empty(); }), res.end());
        return res;
    }

private:
    usize n_{};
    std::vector<i32> data_;
};

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/Tree.hpp"

#line 4 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/Tree.hpp"

#line 7 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/Tree.hpp"

namespace zawa {

using Tree = std::vector<std::vector<u32>>;

void AddEdge(Tree& T, u32 u, u32 v) {
    assert(u < T.size());
    assert(v < T.size());
    T[u].emplace_back(v);
    T[v].emplace_back(u);
}

void AddDirectedEdge(Tree& T, u32 from, u32 to) {
    assert(from < T.size());
    assert(to < T.size());
    T[from].emplace_back(to);
}

} // namespace zawa
#line 5 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"

#line 8 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"
#include <cmath>
#include <limits>
#include <utility>
#line 12 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"

namespace zawa {

class HeavyLightDecomposition {
public:
    using Vertex = u32;

    static constexpr Vertex Invalid() noexcept {
        return INVALID;
    }

    HeavyLightDecomposition() = default;

    HeavyLightDecomposition(Tree T, Vertex root = 0u) 
        : n_{T.size()}, par_(n_), top_(n_), idx_(n_), 
        inv_(n_), size_(n_, usize{1}), dep_(n_) {

            auto dfs1{[&](auto dfs, Vertex v, Vertex p, usize d) -> usize {
                par_[v] = p;
                dep_[v] = d;
                if (p != INVALID) {
                    for (u32 i{} ; i + 1 < T[v].size() ; i++) if (T[v][i] == p) {
                        std::swap(T[v][i], T[v].back());
                        break;
                    }
                    assert(T[v].back() == p);
                    T[v].pop_back();
                }
                for (Vertex x : T[v]) {
                    size_[v] += dfs(dfs, x, v, d + 1);
                }
                for (u32 i{1} ; i < T[v].size() ; i++) if (size_[T[v][0]] < size_[T[v][i]]) {
                    std::swap(T[v][0], T[v][i]);
                }
                return size_[v];
            }};

            auto dfs2{[&](auto dfs, Vertex v, Vertex idx, Vertex top) -> Vertex {
                idx_[v] = idx++;
                inv_[idx_[v]] = v;
                top_[v] = top;
                if (T[v].size()) {
                    idx = dfs(dfs, T[v][0], idx, top);
                    for (u32 i{1} ; i < T[v].size() ; i++) {
                        idx = dfs(dfs, T[v][i], idx, T[v][i]);
                    }
                }
                return idx;
            }};

            dfs1(dfs1, root, INVALID, 0u);
            dfs2(dfs2, root, 0u, root);
        }

    inline usize size() const noexcept {
        return n_;
    }

    usize size(Vertex v) const noexcept {
        assert(v < size());
        return size_[v];
    }

    usize depth(Vertex v) const noexcept {
        assert(v < size());
        return dep_[v];
    }

    Vertex parent(Vertex v) const noexcept {
        assert(v < size());
        return par_[v];
    }

    Vertex index(Vertex v) const noexcept {
        assert(v < size());
        return idx_[v];
    }

    Vertex operator[](Vertex v) const noexcept {
        assert(v < size());
        return idx_[v];
    }


    std::vector<std::pair<Vertex, Vertex>> decomp(Vertex s, Vertex t) const {
        assert(s < size());
        assert(t < size());
        std::vector<std::pair<Vertex, Vertex>> res, ser;
        while (top_[s] != top_[t]) {
            if (dep_[top_[s]] >= dep_[top_[t]]) {
                res.emplace_back(s, top_[s]);
                s = top_[s];
                if (par_[s] != INVALID) s = par_[s];
            }
            else {
                ser.emplace_back(top_[t], t);
                t = top_[t];
                if (par_[t] != INVALID) t = par_[t];
            }
        }
        res.emplace_back(s, t);
        std::reverse(ser.begin(), ser.end());
        res.insert(res.end(), ser.begin(), ser.end()); 
        return res;
    }

    std::vector<std::pair<Vertex, Vertex>> operator()(Vertex s, Vertex t) const {
        return decomp(s, t);
    }

    Vertex lca(u32 u, u32 v) const {
        assert(u < size());
        assert(v < size());
        while (top_[u] != top_[v]) {
            if (dep_[top_[u]] >= dep_[top_[v]]) {
                u = top_[u];
                if (par_[u] != INVALID) u = par_[u];
            }
            else {
                v = top_[v];
                if (par_[v] != INVALID) v = par_[v];
            }
        }
        return (dep_[u] <= dep_[v] ? u : v);
    }

    // pはvの祖先か？
    bool isAncestor(Vertex v, Vertex p) {
        assert(v < size());
        assert(p < size());
        if (dep_[v] < dep_[p]) return false;
        while (v != INVALID and top_[v] != top_[p]) {
            v = par_[top_[v]];
        }
        return v != INVALID;
    }

    Vertex levelAncestor(Vertex v, usize step) const {
        assert(v < size());
        if (step > dep_[v]) return INVALID;
        while (true) {
            usize dist{dep_[v] - dep_[top_[v]]};
            if (dist >= step) break;
            step -= dist + 1;
            v = par_[top_[v]];
        }
        step = (dep_[v] - dep_[top_[v]]) - step;
        return inv_[idx_[top_[v]] + step];
    }

    Vertex jump(Vertex s, Vertex t, usize step) const {
        assert(s < size());
        assert(t < size());
        Vertex uu{INVALID}, vv{INVALID};
        usize d{};
        for (auto [u, v] : decomp(s, t)) {
            usize dist{std::max(dep_[u], dep_[v]) - std::min(dep_[u], dep_[v])};
            if (dist >= step) {
                uu = u;
                vv = v;
                d = dist;
                break;
            }
            step -= dist + 1;
        }
        if (uu == INVALID) return INVALID;
        if (dep_[uu] <= dep_[vv]) {
            return inv_[idx_[uu] + step];
        }
        else {
            return inv_[idx_[vv] + (d - step)];
        }
    }

    usize distance(Vertex s, Vertex t) const {
        assert(s < size());
        assert(t < size());
        usize res{};
        for (auto [u, v] : decomp(s, t)) {
            if (dep_[u] > dep_[v]) std::swap(u, v);
            res += dep_[v] - dep_[u];
        }
        return res;
    }

private:
    static constexpr Vertex INVALID{static_cast<Vertex>(-1)};
    usize n_{};
    std::vector<Vertex> par_{}, top_{}, idx_{}, inv_{};
    std::vector<usize> size_{}, dep_{};
};

} // namespace zawa
#line 7 "2559.test.cpp"

#line 10 "2559.test.cpp"
#include <tuple>
#line 13 "2559.test.cpp"

using namespace zawa;

struct MIN {
    using Element = int;
    static Element identity() {
        return (int)2e9;
    }
    static Element operation(Element L, Element R) {
        return std::min(L, R);
    }
};

int main() {
    SetFastIO();

    int N, M;
    std::cin >> N >> M;
    std::vector<std::tuple<int, int, int, int>> E(M);
    for (int i{} ; auto& [w, a, b, id] : E) {
        std::cin >> a >> b >> w;
        a--; b--;
        id = i++;
    }
    std::sort(E.begin(), E.end());
    DisjointSetUnion dsu(N);  
    std::vector<int> id(M, -1);
    int use_edge{};
    long long base{};
    for (auto [w, a, b, i] : E) {
        if (dsu.same(a, b)) continue;
        base += w;
        dsu.merge(a, b);
        id[i] = N + use_edge++;
    }
    assert(use_edge <= N - 1);
    if (use_edge < N - 1) {
        for (int i{} ; i < M ; i++) std::cout << -1 << '\n';
        return 0;
    }
    Tree T(N + N - 1);
    for (auto [_, a, b, i] : E) if (id[i] != -1) {
        AddEdge(T, a, id[i]);
        AddEdge(T, b, id[i]);
    }
    HeavyLightDecomposition hld{T};
    const int INF{MIN::identity()};
    DualSparseTable<MIN> spt{std::vector<int>(N + N - 1, INF)};
    for (auto [w, a, b, i] : E) if (id[i] == -1) {
        for (auto [l, r] : hld(a, b)) {
            l = hld[l];
            r = hld[r];
            if (l > r) std::swap(l, r);
            spt.operation(l, r + 1, w);
        }
    }
    auto prod{spt.build()};
    std::vector<long long> ans(M, -1LL);
    for (auto [w, a, b, i] : E) {
        if (id[i] == -1) ans[i] = base;
        else {
            int find{prod[hld[id[i]]]};
            ans[i] = (find == INF ? -1LL : base - w + find);
        }
    }
    for (int i{} ; i < M ; i++) {
        std::cout << ans[i] << '\n';
    }
}
accuracy: 1
time_ms: 100
memory_kb: 64900
final_rank: 6

code_snippet: #line 1 "2559.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/2559"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Template/IOSetting.hpp"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Template/TypeAlias.hpp"

#include <cstdint>
#include <cstddef>

namespace zawa {

using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;

using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;

using usize = std::size_t;

} // namespace zawa
#line 4 "/home/zawatin/compro/cp-documentation/Src/Template/IOSetting.hpp"

#include <iostream>
#include <iomanip>

namespace zawa {

void SetFastIO() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
}

void SetPrecision(u32 dig) {
    std::cout << std::fixed << std::setprecision(dig);
}

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/DataStructure/SparseTable/DualSparseTable.hpp"

#line 4 "/home/zawatin/compro/cp-documentation/Src/DataStructure/SparseTable/DualSparseTable.hpp"

#include <vector>
#include <cassert>

namespace zawa {

template <class S>
class DualSparseTable {
public:
    using Value = typename S::Element;

    DualSparseTable() = default;
    
    DualSparseTable(const std::vector<Value>& A)
        : n_{A.size()}, L_(A.size() + 1), dat_{} {
        
        assert(A.size());
        for (u32 i{1} ; i < L_.size() ; i++) {
            L_[i] = L_[i - 1] + (i >> (L_[i - 1] + 1));
        }
        dat_ = std::vector(L_.back() + 1, std::vector(A.size(), S::identity()));
        dat_[0] = A;
    }

    void operation(u32 L, u32 R, const Value& v) {
        assert(L <= R and R <= size());
        if (L == R) {
            return;
        }
        else if (L + 1 == R) {
            dat_[0][L] = S::operation(dat_[0][L], v);
        }
        else {
            u32 now{L_[R - L]};
            dat_[now][L] = S::operation(dat_[now][L], v);
            dat_[now][R - (1 << now)] = S::operation(dat_[now][R - (1 << now)], v);
        }
    }

    constexpr usize size() const {
        return n_;
    }

    std::vector<Value> build() {
        assert(dat_.size() >= 2u);
        for (u32 i{static_cast<u32>(dat_.size()) - 2u} ; i + 1 < dat_.size() ; i--) {
            for (u32 j{} ; j + (1 << i) < size() ; j++) {
                dat_[i][j] = S::operation(dat_[i][j], dat_[i + 1][j]);
                dat_[i][j + (1 << i)] = S::operation(dat_[i][j + (1 << i)], dat_[i + 1][j]);
            }
        }
        return dat_[0];
    }

private:
    
    usize n_{};
    std::vector<u32> L_;
    std::vector<std::vector<Value>> dat_{};
};

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"

#line 4 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"

#include <algorithm>
#line 7 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"
#include <numeric>
#line 9 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"

namespace zawa {

class DisjointSetUnion {
public:
    DisjointSetUnion() = default;

    DisjointSetUnion(usize n) : n_{n}, data_(n, -1) {
        data_.shrink_to_fit();
    }
    
    u32 leader(u32 v) {
        return data_[v] < 0 ? v : static_cast<u32>(data_[v] = leader(data_[v]));
    }

    bool same(u32 u, u32 v) {
        return leader(u) == leader(v);
    }

    bool merge(u32 u, u32 v) {
        assert(u < n_);
        assert(v < n_);
        u = leader(u);
        v = leader(v);
        if (u == v) return false;
        if (data_[u] > data_[v]) std::swap(u, v);
        data_[u] += data_[v];
        data_[v] = u;
        return true;
    }

    inline usize size() const noexcept {
        return n_;
    }

    usize size(u32 v) {
        assert(v < n_);
        return static_cast<usize>(-data_[leader(v)]);
    }

    std::vector<std::vector<u32>> enumerate() {
        std::vector<std::vector<u32>> res(n_);
        for (u32 v{} ; v < n_ ; v++) {
            res[leader(v)].push_back(v);
        }
        res.erase(std::remove_if(res.begin(), res.end(),
                    [](const auto& arr) -> bool { return arr.empty(); }), res.end());
        return res;
    }

private:
    usize n_{};
    std::vector<i32> data_;
};

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/Tree.hpp"

#line 4 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/Tree.hpp"

#line 7 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/Tree.hpp"

namespace zawa {

using Tree = std::vector<std::vector<u32>>;

void AddEdge(Tree& T, u32 u, u32 v) {
    assert(u < T.size());
    assert(v < T.size());
    T[u].emplace_back(v);
    T[v].emplace_back(u);
}

void AddDirectedEdge(Tree& T, u32 from, u32 to) {
    assert(from < T.size());
    assert(to < T.size());
    T[from].emplace_back(to);
}

} // namespace zawa
#line 5 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"

#line 8 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"
#include <cmath>
#include <limits>
#include <utility>
#line 12 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"

namespace zawa {

class HeavyLightDecomposition {
public:
    using Vertex = u32;

    static constexpr Vertex Invalid() noexcept {
        return INVALID;
    }

    HeavyLightDecomposition() = default;

    HeavyLightDecomposition(Tree T, Vertex root = 0u) 
        : n_{T.size()}, par_(n_), top_(n_), idx_(n_), 
        inv_(n_), size_(n_, usize{1}), dep_(n_) {

            auto dfs1{[&](auto dfs, Vertex v, Vertex p, usize d) -> usize {
                par_[v] = p;
                dep_[v] = d;
                if (p != INVALID) {
                    for (u32 i{} ; i + 1 < T[v].size() ; i++) if (T[v][i] == p) {
                        std::swap(T[v][i], T[v].back());
                        break;
                    }
                    assert(T[v].back() == p);
                    T[v].pop_back();
                }
                for (Vertex x : T[v]) {
                    size_[v] += dfs(dfs, x, v, d + 1);
                }
                for (u32 i{1} ; i < T[v].size() ; i++) if (size_[T[v][0]] < size_[T[v][i]]) {
                    std::swap(T[v][0], T[v][i]);
                }
                return size_[v];
            }};

            auto dfs2{[&](auto dfs, Vertex v, Vertex idx, Vertex top) -> Vertex {
                idx_[v] = idx++;
                inv_[idx_[v]] = v;
                top_[v] = top;
                if (T[v].size()) {
                    idx = dfs(dfs, T[v][0], idx, top);
                    for (u32 i{1} ; i < T[v].size() ; i++) {
                        idx = dfs(dfs, T[v][i], idx, T[v][i]);
                    }
                }
                return idx;
            }};

            dfs1(dfs1, root, INVALID, 0u);
            dfs2(dfs2, root, 0u, root);
        }

    inline usize size() const noexcept {
        return n_;
    }

    usize size(Vertex v) const noexcept {
        assert(v < size());
        return size_[v];
    }

    usize depth(Vertex v) const noexcept {
        assert(v < size());
        return dep_[v];
    }

    Vertex parent(Vertex v) const noexcept {
        assert(v < size());
        return par_[v];
    }

    Vertex index(Vertex v) const noexcept {
        assert(v < size());
        return idx_[v];
    }

    Vertex operator[](Vertex v) const noexcept {
        assert(v < size());
        return idx_[v];
    }


    std::vector<std::pair<Vertex, Vertex>> decomp(Vertex s, Vertex t) const {
        assert(s < size());
        assert(t < size());
        std::vector<std::pair<Vertex, Vertex>> res, ser;
        while (top_[s] != top_[t]) {
            if (dep_[top_[s]] >= dep_[top_[t]]) {
                res.emplace_back(s, top_[s]);
                s = top_[s];
                if (par_[s] != INVALID) s = par_[s];
            }
            else {
                ser.emplace_back(top_[t], t);
                t = top_[t];
                if (par_[t] != INVALID) t = par_[t];
            }
        }
        res.emplace_back(s, t);
        std::reverse(ser.begin(), ser.end());
        res.insert(res.end(), ser.begin(), ser.end()); 
        return res;
    }

    std::vector<std::pair<Vertex, Vertex>> operator()(Vertex s, Vertex t) const {
        return decomp(s, t);
    }

    Vertex lca(u32 u, u32 v) const {
        assert(u < size());
        assert(v < size());
        while (top_[u] != top_[v]) {
            if (dep_[top_[u]] >= dep_[top_[v]]) {
                u = top_[u];
                if (par_[u] != INVALID) u = par_[u];
            }
            else {
                v = top_[v];
                if (par_[v] != INVALID) v = par_[v];
            }
        }
        return (dep_[u] <= dep_[v] ? u : v);
    }

    // pはvの祖先か？
    bool isAncestor(Vertex v, Vertex p) {
        assert(v < size());
        assert(p < size());
        if (dep_[v] < dep_[p]) return false;
        while (v != INVALID and top_[v] != top_[p]) {
            v = par_[top_[v]];
        }
        return v != INVALID;
    }

    Vertex levelAncestor(Vertex v, usize step) const {
        assert(v < size());
        if (step > dep_[v]) return INVALID;
        while (true) {
            usize dist{dep_[v] - dep_[top_[v]]};
            if (dist >= step) break;
            step -= dist + 1;
            v = par_[top_[v]];
        }
        step = (dep_[v] - dep_[top_[v]]) - step;
        return inv_[idx_[top_[v]] + step];
    }

    Vertex jump(Vertex s, Vertex t, usize step) const {
        assert(s < size());
        assert(t < size());
        Vertex uu{INVALID}, vv{INVALID};
        usize d{};
        for (auto [u, v] : decomp(s, t)) {
            usize dist{std::max(dep_[u], dep_[v]) - std::min(dep_[u], dep_[v])};
            if (dist >= step) {
                uu = u;
                vv = v;
                d = dist;
                break;
            }
            step -= dist + 1;
        }
        if (uu == INVALID) return INVALID;
        if (dep_[uu] <= dep_[vv]) {
            return inv_[idx_[uu] + step];
        }
        else {
            return inv_[idx_[vv] + (d - step)];
        }
    }

    usize distance(Vertex s, Vertex t) const {
        assert(s < size());
        assert(t < size());
        usize res{};
        for (auto [u, v] : decomp(s, t)) {
            if (dep_[u] > dep_[v]) std::swap(u, v);
            res += dep_[v] - dep_[u];
        }
        return res;
    }

private:
    static constexpr Vertex INVALID{static_cast<Vertex>(-1)};
    usize n_{};
    std::vector<Vertex> par_{}, top_{}, idx_{}, inv_{};
    std::vector<usize> size_{}, dep_{};
};

} // namespace zawa
#line 7 "2559.test.cpp"

#line 10 "2559.test.cpp"
#include <tuple>
#line 13 "2559.test.cpp"

using namespace zawa;

struct MIN {
    using Element = int;
    static Element identity() {
        return (int)2e9;
    }
    static Element operation(Element L, Element R) {
        return std::min(L, R);
    }
};

int main() {
    SetFastIO();

    int N, M;
    std::cin >> N >> M;
    std::vector<std::tuple<int, int, int, int>> E(M);
    for (int i{} ; auto& [w, a, b, id] : E) {
        std::cin >> a >> b >> w;
        a--; b--;
        id = i++;
    }
    std::sort(E.begin(), E.end());
    DisjointSetUnion dsu(N);  
    std::vector<int> id(M, -1);
    int use_edge{};
    long long base{};
    for (auto [w, a, b, i] : E) {
        if (dsu.same(a, b)) continue;
        base += w;
        dsu.merge(a, b);
        id[i] = N + use_edge++;
    }
    assert(use_edge <= N - 1);
    if (use_edge < N - 1) {
        for (int i{} ; i < M ; i++) std::cout << -1 << '\n';
        return 0;
    }
    Tree T(N + N - 1);
    for (auto [_, a, b, i] : E) if (id[i] != -1) {
        AddEdge(T, a, id[i]);
        AddEdge(T, b, id[i]);
    }
    HeavyLightDecomposition hld{T};
    const int INF{MIN::identity()};
    DualSparseTable<MIN> spt{std::vector<int>(N + N - 1, INF)};
    for (auto [w, a, b, i] : E) if (id[i] == -1) {
        for (auto [l, r] : hld(a, b)) {
            l = hld[l];
            r = hld[r];
            if (l > r) std::swap(l, r);
            spt.operation(l, r + 1, w);
        }
    }
    auto prod{spt.build()};
    std::vector<long long> ans(M, -1LL);
    for (auto [w, a, b, i] : E) {
        if (id[i] == -1) ans[i] = base;
        else {
            int find{prod[hld[id[i]]]};
            ans[i] = (find == INF ? -1LL : base - w + find);
        }
    }
    for (int i{} ; i < M ; i++) {
        std::cout << ans[i] << '\n';
    }
}
accuracy: 1
time_ms: 90
memory_kb: 64896
final_rank: 2

code_snippet: #line 1 "2559.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/02559"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Template/IOSetting.hpp"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Template/TypeAlias.hpp"

#include <cstdint>
#include <cstddef>

namespace zawa {

using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;

using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;

using usize = std::size_t;

} // namespace zawa
#line 4 "/home/zawatin/compro/cp-documentation/Src/Template/IOSetting.hpp"

#include <iostream>
#include <iomanip>

namespace zawa {

void SetFastIO() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
}

void SetPrecision(u32 dig) {
    std::cout << std::fixed << std::setprecision(dig);
}

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/DataStructure/SparseTable/DualSparseTable.hpp"

#line 4 "/home/zawatin/compro/cp-documentation/Src/DataStructure/SparseTable/DualSparseTable.hpp"

#include <vector>
#include <cassert>

namespace zawa {

template <class S>
class DualSparseTable {
public:
    using Value = typename S::Element;

    DualSparseTable() = default;
    
    DualSparseTable(const std::vector<Value>& A)
        : n_{A.size()}, L_(A.size() + 1), dat_{} {
        
        assert(A.size());
        for (u32 i{1} ; i < L_.size() ; i++) {
            L_[i] = L_[i - 1] + (i >> (L_[i - 1] + 1));
        }
        dat_ = std::vector(L_.back() + 1, A);
    }

    void operation(u32 L, u32 R, const Value& v) {
        assert(L <= R and R <= size());
        if (L == R) {
            return;
        }
        else if (L + 1 == R) {
            dat_[0][L] = S::operation(dat_[0][L], v);
        }
        else {
            u32 now{L_[R - L]};
            dat_[now][L] = S::operation(dat_[now][L], v);
            dat_[now][R - (1 << now)] = S::operation(dat_[now][R - (1 << now)], v);
        }
    }

    constexpr usize size() const {
        return n_;
    }

    std::vector<Value> build() {
        assert(dat_.size() >= 2u);
        for (u32 i{static_cast<u32>(dat_.size()) - 2u} ; i + 1 < dat_.size() ; i--) {
            for (u32 j{} ; j + (1 << i) < size() ; j++) {
                dat_[i][j] = S::operation(dat_[i][j], dat_[i + 1][j]);
                dat_[i][j + (1 << i)] = S::operation(dat_[i][j + (1 << i)], dat_[i + 1][j]);
            }
        }
        return dat_[0];
    }

private:
    
    usize n_{};
    std::vector<u32> L_;
    std::vector<std::vector<Value>> dat_{};
};

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"

#line 4 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"

#include <algorithm>
#line 7 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"
#include <numeric>
#line 9 "/home/zawatin/compro/cp-documentation/Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"

namespace zawa {

class DisjointSetUnion {
public:
    DisjointSetUnion() = default;

    DisjointSetUnion(usize n) : n_{n}, data_(n, -1) {
        data_.shrink_to_fit();
    }
    
    u32 leader(u32 v) {
        return data_[v] < 0 ? v : static_cast<u32>(data_[v] = leader(data_[v]));
    }

    bool same(u32 u, u32 v) {
        return leader(u) == leader(v);
    }

    bool merge(u32 u, u32 v) {
        assert(u < n_);
        assert(v < n_);
        u = leader(u);
        v = leader(v);
        if (u == v) return false;
        if (data_[u] > data_[v]) std::swap(u, v);
        data_[u] += data_[v];
        data_[v] = u;
        return true;
    }

    inline usize size() const noexcept {
        return n_;
    }

    usize size(u32 v) {
        assert(v < n_);
        return static_cast<usize>(-data_[leader(v)]);
    }

    std::vector<std::vector<u32>> enumerate() {
        std::vector<std::vector<u32>> res(n_);
        for (u32 v{} ; v < n_ ; v++) {
            res[leader(v)].push_back(v);
        }
        res.erase(std::remove_if(res.begin(), res.end(),
                    [](const auto& arr) -> bool { return arr.empty(); }), res.end());
        return res;
    }

private:
    usize n_{};
    std::vector<i32> data_;
};

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/Tree.hpp"

#line 4 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/Tree.hpp"

#line 7 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/Tree.hpp"

namespace zawa {

using Tree = std::vector<std::vector<u32>>;

void AddEdge(Tree& T, u32 u, u32 v) {
    assert(u < T.size());
    assert(v < T.size());
    T[u].emplace_back(v);
    T[v].emplace_back(u);
}

void AddDirectedEdge(Tree& T, u32 from, u32 to) {
    assert(from < T.size());
    assert(to < T.size());
    T[from].emplace_back(to);
}

} // namespace zawa
#line 5 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"

#line 8 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"
#include <cmath>
#include <limits>
#include <utility>
#line 12 "/home/zawatin/compro/cp-documentation/Src/Graph/Tree/HeavyLightDecomposition.hpp"

namespace zawa {

class HeavyLightDecomposition {
public:
    using Vertex = u32;

    static constexpr Vertex Invalid() noexcept {
        return INVALID;
    }

    HeavyLightDecomposition() = default;

    HeavyLightDecomposition(Tree T, Vertex root = 0u) 
        : n_{T.size()}, par_(n_), top_(n_), idx_(n_), 
        inv_(n_), size_(n_, usize{1}), dep_(n_) {

            auto dfs1{[&](auto dfs, Vertex v, Vertex p, usize d) -> usize {
                par_[v] = p;
                dep_[v] = d;
                if (p != INVALID) {
                    for (u32 i{} ; i + 1 < T[v].size() ; i++) if (T[v][i] == p) {
                        std::swap(T[v][i], T[v].back());
                        break;
                    }
                    assert(T[v].back() == p);
                    T[v].pop_back();
                }
                for (Vertex x : T[v]) {
                    size_[v] += dfs(dfs, x, v, d + 1);
                }
                for (u32 i{1} ; i < T[v].size() ; i++) if (size_[T[v][0]] < size_[T[v][i]]) {
                    std::swap(T[v][0], T[v][i]);
                }
                return size_[v];
            }};

            auto dfs2{[&](auto dfs, Vertex v, Vertex idx, Vertex top) -> Vertex {
                idx_[v] = idx++;
                inv_[idx_[v]] = v;
                top_[v] = top;
                if (T[v].size()) {
                    idx = dfs(dfs, T[v][0], idx, top);
                    for (u32 i{1} ; i < T[v].size() ; i++) {
                        idx = dfs(dfs, T[v][i], idx, T[v][i]);
                    }
                }
                return idx;
            }};

            dfs1(dfs1, root, INVALID, 0u);
            dfs2(dfs2, root, 0u, root);
        }

    inline usize size() const noexcept {
        return n_;
    }

    usize size(Vertex v) const noexcept {
        assert(v < size());
        return size_[v];
    }

    usize depth(Vertex v) const noexcept {
        assert(v < size());
        return dep_[v];
    }

    Vertex parent(Vertex v) const noexcept {
        assert(v < size());
        return par_[v];
    }

    Vertex index(Vertex v) const noexcept {
        assert(v < size());
        return idx_[v];
    }

    Vertex operator[](Vertex v) const noexcept {
        assert(v < size());
        return idx_[v];
    }


    std::vector<std::pair<Vertex, Vertex>> decomp(Vertex s, Vertex t) const {
        assert(s < size());
        assert(t < size());
        std::vector<std::pair<Vertex, Vertex>> res, ser;
        while (top_[s] != top_[t]) {
            if (dep_[top_[s]] >= dep_[top_[t]]) {
                res.emplace_back(s, top_[s]);
                s = top_[s];
                if (par_[s] != INVALID) s = par_[s];
            }
            else {
                ser.emplace_back(top_[t], t);
                t = top_[t];
                if (par_[t] != INVALID) t = par_[t];
            }
        }
        res.emplace_back(s, t);
        std::reverse(ser.begin(), ser.end());
        res.insert(res.end(), ser.begin(), ser.end()); 
        return res;
    }

    std::vector<std::pair<Vertex, Vertex>> operator()(Vertex s, Vertex t) const {
        return decomp(s, t);
    }

    Vertex lca(u32 u, u32 v) const {
        assert(u < size());
        assert(v < size());
        while (top_[u] != top_[v]) {
            if (dep_[top_[u]] >= dep_[top_[v]]) {
                u = top_[u];
                if (par_[u] != INVALID) u = par_[u];
            }
            else {
                v = top_[v];
                if (par_[v] != INVALID) v = par_[v];
            }
        }
        return (dep_[u] <= dep_[v] ? u : v);
    }

    // pはvの祖先か？
    bool isAncestor(Vertex v, Vertex p) {
        assert(v < size());
        assert(p < size());
        if (dep_[v] < dep_[p]) return false;
        while (v != INVALID and top_[v] != top_[p]) {
            v = par_[top_[v]];
        }
        return v != INVALID;
    }

    Vertex levelAncestor(Vertex v, usize step) const {
        assert(v < size());
        if (step > dep_[v]) return INVALID;
        while (true) {
            usize dist{dep_[v] - dep_[top_[v]]};
            if (dist >= step) break;
            step -= dist + 1;
            v = par_[top_[v]];
        }
        step = (dep_[v] - dep_[top_[v]]) - step;
        return inv_[idx_[top_[v]] + step];
    }

    Vertex jump(Vertex s, Vertex t, usize step) const {
        assert(s < size());
        assert(t < size());
        Vertex uu{INVALID}, vv{INVALID};
        usize d{};
        for (auto [u, v] : decomp(s, t)) {
            usize dist{std::max(dep_[u], dep_[v]) - std::min(dep_[u], dep_[v])};
            if (dist >= step) {
                uu = u;
                vv = v;
                d = dist;
                break;
            }
            step -= dist + 1;
        }
        if (uu == INVALID) return INVALID;
        if (dep_[uu] <= dep_[vv]) {
            return inv_[idx_[uu] + step];
        }
        else {
            return inv_[idx_[vv] + (d - step)];
        }
    }

    usize distance(Vertex s, Vertex t) const {
        assert(s < size());
        assert(t < size());
        usize res{};
        for (auto [u, v] : decomp(s, t)) {
            if (dep_[u] > dep_[v]) std::swap(u, v);
            res += dep_[v] - dep_[u];
        }
        return res;
    }

private:
    static constexpr Vertex INVALID{static_cast<Vertex>(-1)};
    usize n_{};
    std::vector<Vertex> par_{}, top_{}, idx_{}, inv_{};
    std::vector<usize> size_{}, dep_{};
};

} // namespace zawa
#line 7 "2559.test.cpp"

#line 10 "2559.test.cpp"
#include <tuple>
#line 13 "2559.test.cpp"

using namespace zawa;

struct MIN {
    using Element = int;
    static Element operation(Element L, Element R) {
        return std::min(L, R);
    }
};

int main() {
    SetFastIO();

    int N, M;
    std::cin >> N >> M;
    std::vector<std::tuple<int, int, int, int>> E(M);
    for (int i{} ; auto& [w, a, b, id] : E) {
        std::cin >> a >> b >> w;
        a--; b--;
        id = i++;
    }
    std::sort(E.begin(), E.end());
    DisjointSetUnion dsu(N);  
    std::vector<int> id(M, -1);
    int use_edge{};
    long long base{};
    for (auto [w, a, b, i] : E) {
        if (dsu.same(a, b)) continue;
        base += w;
        dsu.merge(a, b);
        id[i] = N + use_edge++;
    }
    assert(use_edge <= N - 1);
    if (use_edge < N - 1) {
        for (int i{} ; i < M ; i++) std::cout << -1 << '\n';
        return 0;
    }
    Tree T(N + N - 1);
    for (auto [_, a, b, i] : E) if (id[i] != -1) {
        AddEdge(T, a, id[i]);
        AddEdge(T, b, id[i]);
    }
    HeavyLightDecomposition hld{T};
    const int INF{(int)2e9};
    DualSparseTable<MIN> spt{std::vector<int>(N + N - 1, INF)};
    for (auto [w, a, b, i] : E) if (id[i] == -1) {
        for (auto [l, r] : hld(a, b)) {
            l = hld[l];
            r = hld[r];
            if (l > r) std::swap(l, r);
            spt.operation(l, r + 1, w);
        }
    }
    auto prod{spt.build()};
    std::vector<long long> ans(M, -1LL);
    for (auto [w, a, b, i] : E) {
        if (id[i] == -1) ans[i] = base;
        else {
            int find{prod[hld[id[i]]]};
            ans[i] = (find == INF ? -1LL : base - w + find);
        }
    }
    for (int i{} ; i < M ; i++) {
        std::cout << ans[i] << '\n';
    }
}
accuracy: 1
time_ms: 100
memory_kb: 64128
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;

struct UnionFind {
  int n;
  vector<int> par;
  
  UnionFind() = default;
  UnionFind(int _n) : n(_n), par(_n) {
    for (int i = 0; i < n; ++i) par[i] = i;
  }
  
  int root(int x) {
    if (par[x] == x) return x;
    else return par[x] = root(par[x]);
  }
  
  bool same(int x, int y) {
    return root(x) == root(y);
  }
  
  void merge(int x, int y) {
    par[root(y)] = root(x);
  }
  
};

/*
使い方
- build() : HLD 分解を行う
  - 探索順に segtree に順番を振ると良い。つまり、
  - seg[i] <- 頂点 rev[i] の情報、とするべき。
- query(int u, int v) : O(log n) 個の列に分解した結果を返す。
  - 返り値は探索順の番号であり、そのまま seg のインデックスとして使える点に注意。
*/
template<class G>
struct HeavyLightDecomposition {
  G g;
  vector<int> siz, in, out, head, rev, par, depth;
  
  HeavyLightDecomposition() = default;
  HeavyLightDecomposition(G &g) : 
    g(g), siz(g.size()), in(g.size()), out(g.size()), head(g.size()), 
    rev(g.size()), par(g.size()), depth(g.size()) { }
  
  void dfs_siz(int idx, int p) {
    par[idx] = p;
    siz[idx] = 1;
    if (g[idx].size() && g[idx][0] == p) swap(g[idx][0], g[idx].back());
    for (auto &to : g[idx]) {
      if (to == p) continue;
      dfs_siz(to, idx);
      siz[idx] += siz[to];
      if (siz[g[idx][0]] < siz[to]) swap(g[idx][0], to);
    }
    return;
  }
  
  void dfs_depth(int idx, int par) {
    if (par == -1) depth[idx] = 0;
    else depth[idx] = depth[par] + 1;
    
    for (auto &to : g[idx]) {
      if (to == par) continue;
      dfs_depth(to, idx);
    }
    return;
  }
  
  void dfs_hld(int idx, int par, int &times) {
    in[idx] = times++;
    rev[in[idx]] = idx;
    for (auto &to : g[idx]) {
      if (to == par) continue;
      head[to] = (g[idx][0] == to ? head[idx] : to);
      dfs_hld(to, idx, times);
    }
    out[idx] = times;
    return;
  }
  
  void build() {
    dfs_siz(0, -1);
    dfs_depth(0, -1);
    int t = 0;
    dfs_hld(0, -1, t);
    return;
  }
  
  // Todo : u -> v に向けた順番で返す
  vector< array<int, 2> > query(int u, int v) {
    vector< array<int, 2> > left;
    vector< array<int, 2> > right;
    while (head[u] != head[v]) {
      if (depth[head[u]] > depth[head[v]]) {
        left.push_back({in[head[u]], in[u]});
        u = par[head[u]];
      }
      else {
        right.push_back({in[head[v]], in[v]});
        v = par[head[v]];
      }
    }
    left.push_back({min(in[u], in[v]), max(in[u], in[v])});
    while (right.size()) {
      left.emplace_back(right.back());
      right.pop_back();
    }
    return left;
  }
  
};

template<class Monoid>
struct DualSegmentTree {
  using F = function<Monoid(Monoid, Monoid)>;
  
  int sz;
  vector<Monoid> seg;
  
  const F f;
  const Monoid M1;
  
  DualSegmentTree(int n, const F f, const Monoid &M1) : f(f), M1(M1) {
    sz = 1;
    while (sz < n) sz <<= 1;
    seg.assign(2 * sz, M1);
  }
  
  // void set(int k, const Monoid &x) {seg[k + sz] = x;}
  
  // void build() {
  //   for (int k = sz - 1; k > 0; --k) {
  //     seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
  //   }
  // }
  
  Monoid get(int k) {
    k += sz;
    Monoid ret = seg[k];
    while (k >>= 1) {
      ret = f(seg[k], ret);
    }
    return ret;
  }
  
  void update(int a, int b, const Monoid &x) {
    for (a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
      if (a & 1) seg[a] = f(seg[a], x), a++;
      if (b & 1) --b, seg[b] = f(seg[b], x);
    }
  }
  
};

ll op(ll a, ll b) {return min(a, b);}

int main() {
  int N, M; cin >> N >> M;
  vector<array<int, 4>> edge(M);
  for (int i = 0; i < M; ++i) {
    int u, v, w; cin >> u >> v >> w;
    u--, v--;
    edge[i] = {w, u, v, i};
  }  
  sort(edge.begin(), edge.end());
  
  UnionFind uf(N);
  vector<vector<int>> tree(2*N-1);
  
  long long mst = 0;
  int id = N;
  const ll INF = 1e18;
  vector<ll> num(M, -1);
  for (auto [w, u, v, ed] : edge) {
    if (uf.same(u, v)) continue;
    mst += w;
    
    uf.merge(u, v);
    tree[u].emplace_back(id);
    tree[id].emplace_back(u);
    tree[v].emplace_back(id);
    tree[id].emplace_back(v);
    num[ed] = id;
    id++;
  }
  
  if (id < 2 * N - 1) {
    for (int i = 0; i < M; ++i) {
      cout << -1 << endl;
    }
    return 0;
  }
  
  HeavyLightDecomposition<vector<vector<int>>> hld(tree);
  hld.build();
  
  // for (int i = 0; i < 2*N-1; ++i) {
  //   cout << hld.in[i] <<  " ";
  // }
  // cout << endl;
  // for (int i = 0; i < 2*N-1; ++i) {
  //   cout << hld.rev[i] << " ";
  // }
  // cout << endl;
  
  DualSegmentTree<ll> seg(2*N-1, op, INF);
  
  for (auto [w, u, v, ed] : edge) {
    if (num[ed] != -1) continue;
    vector<array<int, 2>> ret = hld.query(u, v);
    
    for (auto [s, t] : ret) {
      // cout << s << " " << t << endl;
      seg.update(s, t+1, w);
    }
  }
  
  vector<ll> res(M, 0);
  for (auto [w, u, v, ed] : edge) {
    ll id = num[ed];
    
    if (id == -1) {
      res[ed] = mst;
      continue;
    }
    
    ll e = hld.in[id];
    ll ans = mst - w + seg.get(e);
    assert(ans >= mst);
    res[ed] = (ans < INF ? ans : -1);
  }
  
  for (int i = 0; i < M; ++i) {
    cout << res[i] << endl;
  }
  
  return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 50248
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;

struct UnionFind {
  int n;
  vector<int> par;
  
  UnionFind() = default;
  UnionFind(int _n) : n(_n), par(_n) {
    for (int i = 0; i < n; ++i) par[i] = i;
  }
  
  int root(int x) {
    if (par[x] == x) return x;
    else return par[x] = root(par[x]);
  }
  
  bool same(int x, int y) {
    return root(x) == root(y);
  }
  
  void merge(int x, int y) {
    par[root(y)] = root(x);
  }
  
};

template<class G>
struct HeavyLightDecomposition {
  G g;
  vector<int> siz, in, out, head, rev, par, depth;
  
  HeavyLightDecomposition() = default;
  HeavyLightDecomposition(G &g) : 
    g(g), siz(g.size()), in(g.size()), out(g.size()), head(g.size()), 
    rev(g.size()), par(g.size()), depth(g.size()) { }
    
  void dfs_siz(int idx, int p) {
    par[idx] = p;
    siz[idx] = 1;
    if (g[idx].size() && g[idx][0] == p) swap(g[idx][0], g[idx].back());
    for (auto &to : g[idx]) {
      if (to == p) continue;
      dfs_siz(to, idx);
      siz[idx] += siz[to];
      if (siz[g[idx][0]] < siz[to]) swap(g[idx][0], to);
    }
    return;
  }
  
  void dfs_depth(int idx, int par) {
    if (par == -1) depth[idx] = 0;
    else depth[idx] = depth[par] + 1;
    
    for (auto &to : g[idx]) {
      if (to == par) continue;
      dfs_depth(to, idx);
    }
    return;
  }
  
  void dfs_hld(int idx, int par, int &times) {
    in[idx] = times++;
    rev[in[idx]] = idx;
    for (auto &to : g[idx]) {
      if (to == par) continue;
      head[to] = (g[idx][0] == to ? head[idx] : to);
      dfs_hld(to, idx, times);
    }
    out[idx] = times;
    return;
  }
  
  void build() {
    dfs_siz(0, -1);
    dfs_depth(0, -1);
    int t = 0;
    dfs_hld(0, -1, t);
    return;
  }
  
  vector< array<int, 2> > query(int u, int v) {
    vector< array<int, 2> > ret;
    while (head[u] != head[v]) {
      if (depth[head[u]] > depth[head[v]]) swap(u, v);
      ret.push_back({in[head[v]], in[v]});
      v = par[head[v]];
    }
    ret.push_back({min(in[u], in[v]), max(in[u], in[v])});
    return ret;
  }
  
};

template<class Monoid>
struct DualSegmentTree {
  using F = function<Monoid(Monoid, Monoid)>;
  
  int sz;
  vector<Monoid> seg;
  
  const F f;
  const Monoid M1;
  
  DualSegmentTree(int n, const F f, const Monoid &M1) : f(f), M1(M1) {
    sz = 1;
    while (sz < n) sz <<= 1;
    seg.assign(2 * sz, M1);
  }
  
  // void set(int k, const Monoid &x) {seg[k + sz] = x;}
  
  // void build() {
  //   for (int k = sz - 1; k > 0; --k) {
  //     seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
  //   }
  // }
  
  Monoid get(int k) {
    k += sz;
    Monoid ret = seg[k];
    while (k >>= 1) {
      ret = f(seg[k], ret);
    }
    return ret;
  }
  
  void update(int a, int b, const Monoid &x) {
    for (a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
      if (a & 1) seg[a] = f(seg[a], x), a++;
      if (b & 1) --b, seg[b] = f(seg[b], x);
    }
  }
  
};

ll op(ll a, ll b) {return min(a, b);}

int main() {
  int N, M; cin >> N >> M;
  vector<array<int, 4>> edge(M);
  for (int i = 0; i < M; ++i) {
    int u, v, w; cin >> u >> v >> w;
    u--, v--;
    edge[i] = {w, u, v, i};
  }  
  sort(edge.begin(), edge.end());
  
  UnionFind uf(N);
  vector<vector<int>> tree(2*N-1);
  
  long long mst = 0;
  int id = N;
  const ll INF = 1e18;
  vector<ll> num(M, -1);
  for (auto [w, u, v, ed] : edge) {
    if (uf.same(u, v)) continue;
    mst += w;
    
    uf.merge(u, v);
    tree[u].emplace_back(id);
    tree[id].emplace_back(u);
    tree[v].emplace_back(id);
    tree[id].emplace_back(v);
    num[ed] = id;
    id++;
  }
  
  if (id < 2 * N - 1) {
    for (int i = 0; i < M; ++i) {
      cout << -1 << endl;
    }
    return 0;
  }
  
  HeavyLightDecomposition<vector<vector<int>>> hld(tree);
  hld.build();
  
  // for (int i = 0; i < 2*N-1; ++i) {
  //   cout << hld.in[i] <<  " ";
  // }
  // cout << endl;
  // for (int i = 0; i < 2*N-1; ++i) {
  //   cout << hld.rev[i] << " ";
  // }
  // cout << endl;
  
  DualSegmentTree<ll> seg(2*N-1, op, INF);
  
  for (auto [w, u, v, ed] : edge) {
    if (num[ed] != -1) continue;
    vector<array<int, 2>> ret = hld.query(u, v);
    
    for (auto [s, t] : ret) {
      // cout << s << " " << t << endl;
      seg.update(s, t+1, w);
    }
  }
  
  vector<ll> res(M, 0);
  for (auto [w, u, v, ed] : edge) {
    ll id = num[ed];
    
    if (id == -1) {
      res[ed] = mst;
      continue;
    }
    
    ll e = hld.in[id];
    ll ans = mst - w + seg.get(e);
    assert(ans >= mst);
    res[ed] = (ans < INF ? ans : -1);
  }
  
  for (int i = 0; i < M; ++i) {
    cout << res[i] << endl;
  }
  
  return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 50268
final_rank: 14

code_snippet: #include <bits/stdc++.h>

#include <algorithm>
#include <vector>

namespace nono {

class UnionFind {
  public:
    UnionFind() = default;

    UnionFind(int size): size_(size), data_(size, -1) {}

    int leader(int x) {
        if (data_[x] < 0) {
            return x;
        } else {
            return data_[x] = leader(data_[x]);
        }
    }

    bool merge(int lhs, int rhs) {
        if (same(lhs, rhs)) {
            return false;
        }
        lhs = leader(lhs);
        rhs = leader(rhs);
        if (-data_[lhs] < -data_[rhs]) {
            std::swap(lhs, rhs);
        }
        data_[lhs] += data_[rhs];
        data_[rhs] = lhs;
        return true;
    }

    bool same(int lhs, int rhs) {
        return (leader(lhs) == leader(rhs));
    }

    int size(int x) {
        return -data_[leader(x)];
    }

    int size() const {
        return size_;
    }

    std::vector<std::vector<int>> groups() {
        std::vector<int> leader_buf(size_), group_size(size_);
        for (int i = 0; i < size_; i++) {
            leader_buf[i] = leader(i);
            group_size[leader_buf[i]]++;
        }
        std::vector<std::vector<int>> result(size_);
        for (int i = 0; i < size_; i++) {
            result[i].reserve(group_size[i]);
        }
        for (int i = 0; i < size_; i++) {
            result[leader_buf[i]].push_back(i);
        }
        result.erase(std::remove_if(result.begin(), result.end(), [&](const std::vector<int>& v) { return v.empty(); }),
                     result.end());
        return result;
    }

  private:
    int size_;

    std::vector<int> data_;
};

}  //  namespace nono

using ll = long long;
#define rep(i, l, r) for (ll i = (l); i < (r); i++)
#define rrep(i, r, l) for (ll i = (r); i-- > (l);)
#define all(x) x.begin(), x.end()
template <class T, class U>
bool chmin(T& lhs, U rhs) {
    return lhs > rhs ? (lhs = rhs, true) : false;
}
template <class T, class U>
bool chmax(T& lhs, U rhs) {
    return lhs < rhs ? (lhs = rhs, true) : false;
}
using namespace std;

struct Edge {
    Edge(int t, ll w): to(t), w(w) {}
    int to;
    ll w;
};

using Graph = vector<vector<Edge>>;

class HeavyLightDecomposition {
    static constexpr int NONE = -1;
    using Point = int;
    using Interval = std::pair<int, int>;
    using Intervals = std::vector<std::pair<int, int>>;

  public:
    HeavyLightDecomposition(Graph graph)
        : graph_(std::move(graph)),
          n_(graph_.size()),
          depth_(n_),
          parent_(n_, NONE),
          head_(n_),
          in_(n_),
          out_(n_) {
        set_heavy_edge(0, NONE);
        dfs(0, NONE, 0);
    }

    int lowest_common_ancester(int u, int v) {
        while (head_[u] != head_[v]) {
            if (in_[u] > in_[v]) std::swap(u, v);
            v = parent_[head_[v]];
        }
        return (depth_[u] < depth_[v] ? u : v);
    }

    int distance(int u, int v) {
        return depth_[u] + depth_[v] - 2 * depth_[lowest_common_ancester(u, v)];
    }

    Point vertex(int v) {
        return in_[v];
    }

    Point edge(int u, int v) {
        if (depth_[u] > depth_[v]) std::swap(u, v);
        return in_[v];
    }

    Interval vertices_for_subtree(int u) {
        return subtree(u, true);
    }

    Interval edges_for_subtree(int u) {
        return subtree(u, false);
    }

    Intervals vertices_for_path(int u, int v) {
        return path(u, v, true);
    }

    Intervals edges_for_path(int u, int v) {
        return path(u, v, false);
    }

  private:
    int set_heavy_edge(int u, int p) {
        int size_sum = 1;
        int max_size = 0;
        int max_size_i = 0;
        auto&& adj = graph_[u];
        for (int i = 0; i < (int)adj.size(); i++) {
            const auto& e = adj[i];
            if (e.to == p) continue;
            int size = set_heavy_edge(e.to, u);
            size_sum += size;
            if (max_size < size) {
                max_size = size;
                max_size_i = i;
            }
        }
        if (max_size_i != 0) {
            std::swap(adj[0], adj[max_size_i]);
        }
        return size_sum;
    }

    int dfs(int u, int p, int now) {
        parent_[u] = p;
        in_[u] = now++;
        bool heavy = true;
        for (const auto& e: graph_[u]) {
            if (e.to == p) continue;
            head_[e.to] = (heavy ? head_[u] : e.to);
            depth_[e.to] = depth_[u] + 1;
            heavy = false;
            now = dfs(e.to, u, now);
        }
        out_[u] = now;
        return now;
    }

    Interval subtree(int u, bool vertex) {
        return vertex ? Interval(in_[u], out_[u]) : Interval(in_[u] + 1, out_[u]);
    }

    Intervals path(int u, int v, bool vertex) {
        int l = lowest_common_ancester(u, v);
        Intervals result;
        for (auto w: {u, v}) {
            while (head_[w] != head_[l]) {
                result.emplace_back(in_[head_[w]], in_[w] + 1);
                w = parent_[head_[w]];
            }
            result.emplace_back(in_[l] + 1, in_[w] + 1);
        }
        if (vertex) result.emplace_back(in_[l], in_[l] + 1);
        return result;
    }

    Graph graph_;
    int n_;
    std::vector<int> depth_;
    std::vector<int> parent_;
    std::vector<int> head_;
    std::vector<int> in_;
    std::vector<int> out_;
};

const ll NONE = -1;
struct Data {
    set<int> s;
    vector<ll> a;
    Data(int n): a(n, NONE) {
        rep(i, 0, n) s.insert(i);
    }
    void update(int l, int r, ll x) {
        while (true) {
            auto it = s.lower_bound(l);
            if (it == s.end() || r <= *it) break;
            a[*it] = x;
            s.erase(it);
        }
    }
    ll operator[](int i) {
        return a[i];
    }
};

int main() {
    int n, m;
    cin >> n >> m;
    vector<tuple<ll, int, int, int>> edges;
    rep(i, 0, m) {
        int u, v;
        ll w;
        cin >> u >> v >> w;
        u--;
        v--;
        edges.emplace_back(w, u, v, i);
    }
    ll mst_cost = 0;
    Graph graph(n);
    vector<bool> used(m);
    nono::UnionFind uf(n);
    sort(all(edges));
    for (auto [w, u, v, i]: edges) {
        if (uf.merge(u, v)) {
            used[i] = true;
            mst_cost += w;
            graph[u].emplace_back(v, w);
            graph[v].emplace_back(u, w);
        }
    }
    HeavyLightDecomposition hld(graph);
    Data data(n);
    for (auto [w, u, v, i]: edges) {
        if (used[i]) continue;
        for (auto [l, r]: hld.edges_for_path(u, v)) {
            data.update(l, r, w);
        }
    }
    vector<ll> ans(m);
    for (auto [w, u, v, i]: edges) {
        if (used[i]) {
            ll res = data[hld.edge(u, v)];
            if (res == -1) {
                ans[i] = res;
            } else {
                ans[i] = mst_cost - w + res;
            }
        } else {
            ans[i] = mst_cost;
        }
    }
    rep(i, 0, m) cout << ans[i] << '\n';
}
accuracy: 1
time_ms: 250
memory_kb: 36832
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
using int64 = long long;

struct UnionFind {
  vector<int> data;
  UnionFind(int sz) : data(sz, -1) {}

  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y) return (false);
    if (data[x] > data[y]) swap(x, y);
    data[x] += data[y];
    data[y] = x;
    return (true);
  }

  int find(int k) {
    if (data[k] < 0) return (k);
    return (data[k] = find(data[k]));
  }

  int size(int k) { return (-data[find(k)]); }
};

struct Edge {
  int from, to, cost, idx;

  bool operator<(const Edge &e) const { return (cost < e.cost); }
};

int N, M;
vector<Edge> edges;
vector<int64> ans;
vector<vector<Edge>> tree, g;
vector<set<pair<int, int>>> component;
bool killed[200000];
int64 all = 0;

void rec(int idx, int par = -1) {
  for (auto &e : g[idx])
    component[idx].emplace(e.cost, e.idx);

  for (auto &e : tree[idx]) {
    if (e.to == par) continue;
    rec(e.to, idx);
    auto &u = component[idx], &v = component[e.to];
    if (!v.empty()) {
      ans[e.idx] = all;
      ans[e.idx] -= e.cost;
      ans[e.idx] += v.begin()->first;
    }
    if (u.size() < v.size()) swap(u, v);
    while (!v.empty()) {
      auto p = v.begin();
      if (u.count(*p)) u.erase(*p);
      else u.emplace(*p);
      v.erase(p);
    }
  }
}

int main() {
  ios_base::sync_with_stdio(false); // Fast IO
  cin.tie(NULL); // Untie cin and cout

  cin >> N >> M;

  edges.reserve(M); // Preallocate memory
  ans.resize(M, -1);
  tree.resize(N);
  g.resize(N);
  component.resize(N);

  for (int i = 0; i < M; i++) {
    int a, b, c; cin >> a >> b >> c;
    a--, b--;
    edges.push_back({a, b, c, i});
  }

  UnionFind uf(N);
  sort(begin(edges), end(edges));

  for (auto &e : edges) {
    if (uf.unite(e.to, e.from)) {
      killed[e.idx] = true;
      all += e.cost;
    }
  }

  if (uf.size(0) != N) {
    for (int i = 0; i < M; i++)
      cout << "-1\n";
    return (0);
  }

  for (auto &e : edges) {
    if (killed[e.idx]) {
      tree[e.from].push_back(e);
      tree[e.to].push_back({e.to, e.from, e.cost, e.idx});
    } else {
      g[e.from].push_back(e);
      g[e.to].push_back({e.to, e.from, e.cost, e.idx});
      ans[e.idx] = all;
    }
  }

  rec(0);

  for (auto &a : ans)
    cout << a << "\n";

  return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 44536
final_rank: 7

code_snippet: #include <iostream>
#include <vector>
#include <set>
#include <algorithm>

using namespace std;

struct UnionFind {
  vector<int> data;
  vector<int> component_size; // Added to store component sizes

  UnionFind(int sz) : data(sz, -1), component_size(sz, 1) {} // Initialize component sizes to 1

  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y)
      return (false);
    if (data[x] > data[y])
      swap(x, y);
    data[x] += data[y];
    data[y] = x;
    component_size[x] += component_size[y]; // Update component size
    return (true);
  }

  int find(int k) {
    if (data[k] < 0)
      return (k);
    return (data[k] = find(data[k]));
  }

  int size(int k) { return component_size[find(k)]; } // Return component size directly
};

struct edge1 {
  int u, v, cost, idx;
  bool operator<(const edge1 &e) const { return (cost < e.cost); }
};

struct edge2 {
  int to, cost, idx;
};

int N, M, A[200000], B[200000], C[200000];
vector<edge1> edges;
bool killed[200000];
vector<edge2> tree[100000], g[100000];
int all, ans[200000];
set<pair<int, int>> component[100000];

void rec(int idx, int par = -1) {
  auto& u = component[idx];
  for (auto &e : g[idx]) {
    u.emplace(e.cost, e.idx);
  }
  for (auto &e : tree[idx]) {
    if (e.to == par)
      continue;
    rec(e.to, idx);
    auto &v = component[e.to];
    if (!v.empty()) {
      ans[e.idx] = all;
      ans[e.idx] -= e.cost;
      ans[e.idx] += v.begin()->first;
    }
    if (u.size() < v.size())
      swap(u, v);
    while (!v.empty()) {
      auto p = v.begin();
      if (u.count(*p))
        u.erase(*p);
      else
        u.emplace(*p);
      v.erase(p);
    }
  }
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  
  cin >> N >> M;
  for (int i = 0; i < M; i++) {
    cin >> A[i] >> B[i] >> C[i];
    --A[i], --B[i];
    edges.push_back((edge1){A[i], B[i], C[i], i});
  }
  
  UnionFind uf(N);
  sort(begin(edges), end(edges));
  
  for (auto &e : edges) {
    if (uf.unite(e.v, e.u)) {
      killed[e.idx] = true;
      all += e.cost;
    }
  }
  
  if (uf.size(0) != N) {
    for (int i = 0; i < M; i++)
      cout << "-1\n";
    return (0);
  }
  
  for (int i = 0; i < M; i++) {
    if (killed[i]) {
      tree[A[i]].emplace_back((edge2){B[i], C[i], i});
      tree[B[i]].emplace_back((edge2){A[i], C[i], i});
      ans[i] = -1;
    } else {
      g[A[i]].emplace_back((edge2){B[i], C[i], i});
      g[B[i]].emplace_back((edge2){A[i], C[i], i});
      ans[i] = all;
    }
  }
  
  rec(0);
  
  for (int i = 0; i < M; i++) {
    cout << ans[i] << "\n";
  }
  
  return 0;
}
accuracy: 0.6486486486486487
time_ms: 190
memory_kb: 34112
final_rank: 20

code_snippet: #include <vector>
#include <set>
#include <algorithm>
#include <cstdio>
using namespace std;
using int64 = long long;
struct UnionFind {
  vector<int> data;
  UnionFind(int sz) : data(sz, -1) {}
  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y)
      return (false);
    if (data[x] > data[y])
      swap(x, y);
    data[x] += data[y];
    data[y] = x;
    return (true);
  }
  int find(int k) {
    if (data[k] < 0)
      return (k);
    return (data[k] = find(data[k]));
  }
  int size(int k) { return (-data[find(k)]); }
};
struct edge1 {
  int u, v, cost, idx;
  bool operator<(const edge1 &e) const { return (cost < e.cost); }
};
struct edge2 {
  int to, cost, idx;
};
int N, M, A[200000], B[200000], C[200000];
vector<edge1> edges;
bool killed[200000];
vector<vector<edge2>> tree, g;
int64 all, ans[200000];
vector<set<pair<int, int>>> component;
void rec(int idx, int par = -1) {
  for (auto &e : g[idx]) {
    component[idx].insert({e.cost, e.idx});
  }
  for (auto &e : tree[idx]) {
    if (e.to == par)
      continue;
    rec(e.to, idx);
    if (!component[e.to].empty()) {
      ans[e.idx] = all - e.cost + component[e.to].begin()->first;
    }
    if (component[idx].size() < component[e.to].size()) {
      swap(component[idx], component[e.to]);
    }
    auto it = component[e.to].begin();
    while (it != component[e.to].end()) {
      auto p = *it;
      if (component[idx].count(p)) {
        component[idx].erase(p);
      } else {
        component[idx].insert(p);
      }
      component[e.to].erase(it++);
    }
  }
}
int main() {
  scanf("%d %d", &N, &M);
  tree.resize(N);
  g.resize(N);
  component.resize(N);
  for (int i = 0; i < M; i++) {
    scanf("%d %d %d", &A[i], &B[i], &C[i]);
    --A[i], --B[i];
    edges.push_back({A[i], B[i], C[i], i});
  }
  UnionFind uf(N);
  sort(edges.begin(), edges.end());
  for (auto &e : edges) {
    if (uf.unite(e.v, e.u)) {
      killed[e.idx] = true;
      all += e.cost;
    }
  }
  if (uf.size(0) != N) {
    for (int i = 0; i < M; i++)
      puts("-1");
    return (0);
  }
  for (int i = 0; i < M; i++) {
    if (killed[i]) {
      tree[A[i]].push_back({B[i], C[i], i});
      tree[B[i]].push_back({A[i], C[i], i});
      ans[i] = -1;
    } else {
      g[A[i]].push_back({B[i], C[i], i});
      g[B[i]].push_back({A[i], C[i], i});
      ans[i] = all;
    }
  }
  rec(0);
  for (int i = 0; i < M; i++) {
    printf("%lld\n", ans[i]);
  }
}
accuracy: 1
time_ms: 200
memory_kb: 46364
final_rank: 11

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <set>

using int64 = long long;

struct UnionFind {
  std::vector<int> data;
  UnionFind(int sz) : data(sz, -1) {}
  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y)
      return (false);
    if (data[x] > data[y])
      std::swap(x, y);
    data[x] += data[y];
    data[y] = x;
    return (true);
  }
  int find(int k) {
    if (data[k] < 0)
      return (k);
    return (data[k] = find(data[k]));
  }
  int size(int k) { return (-data[find(k)]); }
};

struct edge1 {
  int u, v, cost, idx;
  bool operator<(const edge1 &e) const { return (cost < e.cost); }
};

struct edge2 {
  int to, cost, idx;
};

int N, M, A[200000], B[200000], C[200000];
std::vector<edge1> edges;
bool killed[200000];
std::vector<edge2> tree[100000], g[100000];
int64 all, ans[200000];
std::set<std::pair<int, int>> component[100000];

void rec(int idx, int par = -1) {
  for (const auto &e : g[idx]) {
    component[idx].emplace(e.cost, e.idx);
  }
  for (const auto &e : tree[idx]) {
    if (e.to == par) continue;
    rec(e.to, idx);
    auto &u = component[idx], &v = component[e.to];
    if (!v.empty()) {
      ans[e.idx] = all;
      ans[e.idx] -= e.cost;
      ans[e.idx] += v.begin()->first;
    }
    if (u.size() < v.size())
      std::swap(u, v);
    while (!v.empty()) {
      auto p = v.begin();
      if (u.count(*p)) u.erase(*p);
      else u.emplace(*p);
      v.erase(p);
    }
  }
}

int main() {
  std::cin >> N >> M;
  for (int i = 0; i < M; i++) {
    std::cin >> A[i] >> B[i] >> C[i];
    --A[i], --B[i];
    edges.push_back({A[i], B[i], C[i], i});
  }
  UnionFind uf(N);
  std::sort(edges.begin(), edges.end());
  for (const auto &e : edges) {
    if (uf.unite(e.v, e.u)) {
      killed[e.idx] = true;
      all += e.cost;
    }
  }
  if (uf.size(0) != N) {
    for (int i = 0; i < M; i++)
      std::cout << "-1\n";
    return 0;
  }
  for (int i = 0; i < M; i++) {
    if (killed[i]) {
      tree[A[i]].push_back({B[i], C[i], i});
      tree[B[i]].push_back({A[i], C[i], i});
      ans[i] = -1;
    } else {
      g[A[i]].push_back({B[i], C[i], i});
      g[B[i]].push_back({A[i], C[i], i});
      ans[i] = all;
    }
  }
  rec(0);
  for (int i = 0; i < M; i++) {
    std::cout << ans[i] << "\n";
  }
  return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 48108
final_rank: 16

code_snippet: #include <cstdio>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
using int64 = long long;
struct UnionFind {
  vector<int> data;
  UnionFind(int sz) : data(sz, -1) {}
  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y)
      return (false);
    if (data[x] > data[y])
      swap(x, y);
    data[x] += data[y];
    data[y] = x;
    return (true);
  }
  int find(int k) {
    if (data[k] < 0)
      return (k);
    return (data[k] = find(data[k]));
  }
  int size(int k) { return (-data[find(k)]); }
};
struct edge1 {
  int u, v, cost, idx;
  bool operator<(const edge1 &e) const { return (cost < e.cost); }
};
struct edge2 {
  int to, cost, idx;
};
int N, M, A[200000], B[200000], C[200000];
vector<edge1> edges;
bool killed[200000];
vector<edge2> tree[100000], g[100000];
int64 all, ans[200000];
set<pair<int, int>> component[100000];
void rec(int idx, int par = -1) {
  for (auto &e : g[idx]) {
    component[idx].emplace(e.cost, e.idx);
  }
  for (auto &e : tree[idx]) {
    if (e.to == par)
      continue;
    rec(e.to, idx);
    auto &u = component[idx], &v = component[e.to];
    if (!v.empty()) {
      ans[e.idx] = all;
      ans[e.idx] -= e.cost;
      ans[e.idx] += v.begin()->first;
    }
    if (u.size() < v.size())
      swap(u, v);
    while (!v.empty()) {
      auto p = v.begin();
      if (u.count(*p))
        u.erase(*p);
      else
        u.emplace(*p);
      v.erase(p);
    }
  }
}
int main() {
  scanf("%d %d", &N, &M);
  edges.reserve(M);
  for (int i = 0; i < M; i++) {
    scanf("%d %d %d", &A[i], &B[i], &C[i]);
    --A[i], --B[i];
    edges.push_back((edge1){A[i], B[i], C[i], i});
  }
  UnionFind uf(N);
  sort(begin(edges), end(edges));
  for (auto &e : edges) {
    if (uf.unite(e.v, e.u)) {
      killed[e.idx] = true;
      all += e.cost;
    }
  }
  if (uf.size(0) != N) {
    for (int i = 0; i < M; i++)
      printf("-1\n");
    return (0);
  }
  for (int i = 0; i < M; i++) {
    if (killed[i]) {
      tree[A[i]].push_back((edge2){B[i], C[i], i});
      tree[B[i]].push_back((edge2){A[i], C[i], i});
      ans[i] = -1;
    } else {
      g[A[i]].push_back((edge2){B[i], C[i], i});
      g[B[i]].push_back((edge2){A[i], C[i], i});
      ans[i] = all;
    }
  }
  rec(0);
  for (int i = 0; i < M; i++) {
    printf("%lld\n", ans[i]);
  }
}
accuracy: 1
time_ms: 190
memory_kb: 47356
final_rank: 8

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
using int64 = long long;
struct UnionFind {
  vector<int> data;
  UnionFind(int sz) : data(sz, -1) {}
  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y)
      return (false);
    if (data[x] > data[y])
      swap(x, y);
    data[x] += data[y];
    data[y] = x;
    return (true);
  }
  int find(int k) {
    if (data[k] < 0)
      return (k);
    return (data[k] = find(data[k]));
  }
  int size(int k) { return (-data[find(k)]); }
};
struct edge1 {
  int u, v, cost, idx;
  bool operator<(const edge1 &e) const { return (cost < e.cost); }
};
struct edge2 {
  int to, cost, idx;
};
int N, M, A[200000], B[200000], C[200000];
vector<edge1> edges;
bool killed[200000];
vector<edge2> tree[100000], g[100000];
int64 all, ans[200000];
set<pair<int, int>> component[100000];
void rec(int idx, int par = -1) {
  for (auto &e : g[idx]) {
    component[idx].emplace(e.cost, e.idx);
  }
  for (auto &e : tree[idx]) {
    if (e.to == par)
      continue;
    rec(e.to, idx);
    auto &u = component[idx], &v = component[e.to];
    if (!v.empty()) {
      ans[e.idx] = all;
      ans[e.idx] -= e.cost;
      ans[e.idx] += v.begin()->first;
    }
    if (u.size() < v.size())
      swap(u, v);
    while (!v.empty()) {
      auto p = v.begin();
      if (u.count(*p))
        u.erase(*p);
      else
        u.emplace(*p);
      v.erase(p);
    }
  }
}
int main() {
  ios_base::sync_with_stdio(false); cin.tie(NULL);
  scanf("%d %d", &N, &M);
  edges.reserve(M);
  for (int i = 0; i < M; i++) {
    scanf("%d %d %d", &A[i], &B[i], &C[i]);
    --A[i], --B[i];
    edges.push_back((edge1){A[i], B[i], C[i], i});
  }
  UnionFind uf(N);
  sort(begin(edges), end(edges));
  for (auto &e : edges) {
    if (uf.unite(e.v, e.u)) {
      killed[e.idx] = true;
      all += e.cost;
    }
  }
  if (uf.size(0) != N) {
    for (int i = 0; i < M; i++)
      puts("-1");
    return (0);
  }
  for (int i = 0; i < M; i++) {
    if (killed[i]) {
      tree[A[i]].emplace_back((edge2){B[i], C[i], i});
      tree[B[i]].emplace_back((edge2){A[i], C[i], i});
      ans[i] = -1;
    } else {
      g[A[i]].emplace_back((edge2){B[i], C[i], i});
      g[B[i]].emplace_back((edge2){A[i], C[i], i});
      ans[i] = all;
    }
  }
  rec(0);
  for (int i = 0; i < M; i++) {
    printf("%lld\n", ans[i]);
  }
}
accuracy: 1
time_ms: 190
memory_kb: 47700
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
using int64 = long long;

struct UnionFind {
  vector<int> data;
  UnionFind(int sz) : data(sz, -1) {}
  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y)
      return (false);
    if (data[x] > data[y])
      swap(x, y);
    data[x] += data[y];
    data[y] = x;
    return (true);
  }
  int find(int k) {
    if (data[k] < 0)
      return (k);
    return (data[k] = find(data[k]));
  }
  int size(int k) { return (-data[find(k)]); }
};

struct edge1 {
  int u, v, cost, idx;
  bool operator<(const edge1 &e) const { return (cost < e.cost); }
};

struct edge2 {
  int to, cost, idx;
};

int N, M, A[200000], B[200000], C[200000];
vector<edge1> edges;
bool killed[200000];
vector<edge2> tree[100000], g[100000];
int64 all, ans[200000];
set<pair<int, int>> component[100000];

void rec(int idx, int par = -1) {
  for (auto &e : g[idx]) {
    component[idx].emplace(e.cost, e.idx);
  }
  for (auto &e : tree[idx]) {
    if (e.to == par)
      continue;
    rec(e.to, idx);
    auto &u = component[idx], &v = component[e.to];
    if (!v.empty()) {
      ans[e.idx] = all;
      ans[e.idx] -= e.cost;
      ans[e.idx] += v.begin()->first;
    }
    if (u.size() < v.size())
      swap(u, v);
    while (!v.empty()) {
      auto p = v.begin();
      if (u.count(*p))
        u.erase(*p);
      else
        u.emplace(*p);
      v.erase(p);
    }
  }
}

int main() {
  std::ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  scanf("%d %d", &N, &M);
  edges.reserve(M);
  for (int i = 0; i < M; i++) {
    scanf("%d %d %d", &A[i], &B[i], &C[i]);
    --A[i], --B[i];
    edges.emplace_back((edge1){A[i], B[i], C[i], i});
  }
  UnionFind uf(N);
  sort(begin(edges), end(edges));
  for (auto &e : edges) {
    if (uf.unite(e.v, e.u)) {
      killed[e.idx] = true;
      all += e.cost;
    }
  }
  if (uf.size(0) != N) {
    for (int i = 0; i < M; i++)
      puts("-1");
    return (0);
  }
  for (int i = 0; i < M; i++) {
    if (killed[i]) {
      tree[A[i]].emplace_back((edge2){B[i], C[i], i});
      tree[B[i]].emplace_back((edge2){A[i], C[i], i});
      ans[i] = -1;
    } else {
      g[A[i]].emplace_back((edge2){B[i], C[i], i});
      g[B[i]].emplace_back((edge2){A[i], C[i], i});
      ans[i] = all;
    }
  }
  rec(0);
  for (int i = 0; i < M; i++) {
    printf("%lld\n", ans[i]);
  }
}
accuracy: 1
time_ms: 190
memory_kb: 47800
final_rank: 10

code_snippet: #include <vector>
#include <algorithm>
#include <set>
#include <cstdio>

using int64 = long long;
constexpr int MAX = 200000;

struct UnionFind {
  std::vector<int> data;
  UnionFind(int sz) : data(sz, -1) {}
  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y)
      return false;
    if (data[x] > data[y])
      std::swap(x, y);
    data[x] += data[y];
    data[y] = x;
    return true;
  }
  int find(int k) {
    return data[k] < 0 ? k : (data[k] = find(data[k]));
  }
  int size(int k) { return -data[find(k)]; }
};

struct edge1 {
  int u, v, cost, idx;
  bool operator<(const edge1 &e) const { return cost < e.cost; }
};

struct edge2 {
  int to, cost, idx;
};

int N, M, A[MAX], B[MAX], C[MAX];
edge1 edges[MAX];
bool killed[MAX];
std::vector<edge2> tree[MAX], g[MAX];
int64 all, ans[MAX];
std::set<std::pair<int, int>> component[MAX];

void rec(int idx, int par = -1) {
  for (auto &e : g[idx]) {
    component[idx].emplace(e.cost, e.idx);
  }
  for (auto &e : tree[idx]) {
    if (e.to == par)
      continue;
    rec(e.to, idx);
    auto &u = component[idx], &v = component[e.to];
    if (!v.empty()) {
      ans[e.idx] = all - e.cost + v.begin()->first;
    }
    if (u.size() < v.size())
      std::swap(u, v);
    for (auto it = v.begin(); it != v.end(); ) {
      auto p = *it;
      if (u.count(p))
        u.erase(p);
      else
        u.insert(p);
      it = v.erase(it);
    }
  }
}

int main() {
  scanf("%d %d", &N, &M);
  for (int i = 0; i < M; i++) {
    scanf("%d %d %d", &A[i], &B[i], &C[i]);
    --A[i], --B[i];
    edges[i] = {A[i], B[i], C[i], i};
  }
  UnionFind uf(N);
  std::sort(edges, edges + M);
  for (int i = 0; i < M; ++i) {
    auto &e = edges[i];
    if (uf.unite(e.v, e.u)) {
      killed[e.idx] = true;
      all += e.cost;
    }
  }
  if (uf.size(0) != N) {
    for (int i = 0; i < M; i++)
      puts("-1");
    return 0;
  }
  for (int i = 0; i < M; i++) {
    if (killed[i]) {
      tree[A[i]].push_back({B[i], C[i], i});
      tree[B[i]].push_back({A[i], C[i], i});
      ans[i] = -1;
    } else {
      g[A[i]].push_back({B[i], C[i], i});
      g[B[i]].push_back({A[i], C[i], i});
      ans[i] = all;
    }
  }
  rec(0);
  for (int i = 0; i < M; i++) {
    printf("%lld\n", ans[i]);
  }
}
accuracy: 1
time_ms: 190
memory_kb: 56632
final_rank: 12