Problem:
Score : 700 points

Problem Statement

Takahashi found an undirected connected graph with N vertices and M edges. The vertices are numbered 1 through N. The i-th edge connects vertices a_i and b_i, and has a weight of c_i.

He will play Q rounds of a game using this graph. In the i-th round, two vertices S_i and T_i are specified, and he will choose a subset of the edges such that any vertex can be reached from at least one of the vertices S_i or T_i by traversing chosen edges.

For each round, find the minimum possible total weight of the edges chosen by Takahashi.

Constraints

1 ≦ N ≦ 4,000

1 ≦ M ≦ 400,000

1 ≦ Q ≦ 100,000

1 ≦ a_i,b_i,S_i,T_i ≦ N

1 ≦ c_i ≦ 10^{9}

a_i \neq b_i

S_i \neq T_i

The given graph is connected.

Partial Scores

In the test set worth 200 points, Q = 1.

In the test set worth another 300 points, Q ≦ 3000.

Input

The input is given from Standard Input in the following format:

N M
a_1 b_1 c_1
a_2 b_2 c_2
:
a_M b_M c_M
Q
S_1 T_1
S_2 T_2
:
S_Q T_Q

Output

Print Q lines. The i-th line should contain the minimum possible total weight of the edges chosen by Takahashi.

Sample Input 1

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

Sample Output 1

8
7

We will examine each round:

In the 1-st round, choosing edges 1 and 3 achieves the minimum total weight of 8.

In the 2-nd round, choosing edges 1 and 2 achieves the minimum total weight of 7.

Sample Input 2

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

Sample Output 2

8

This input satisfies the additional constraints for both partial scores.

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <bits/stdc++.h>
#define rep(i, n) for (lli i = 0; i < (n); i++)
#define rrep(i, n) for (lli i = (n)-1; i >= 0; i--)
using namespace std;
using lli = long long int;
template <class T>
class segtree
{
public:
    lli n;
    vector<T> dat;
    function<T(T, T)> func;
    T dummy;
    segtree<T>(lli _n, function<T(T, T)> f, T dummy) : func(f), dummy(dummy)
    {
        n = 1;
        while (n < _n) {
            n = n * 2;
        }
        dat.assign(2 * n - 1, dummy);
    }
    void update(lli k, T a)
    {
        k += n - 1;
        dat[k] = a;
        while (k > 0) {
            k = (k - 1) / 2;
            dat[k] = func(dat[k * 2 + 1], dat[k * 2 + 2]);
        }
    }
    T query(int a, int b)
    {
        return query(a, b, 0, 0, n);
    }
    // [a,b)の何かを求める.
    T query(int a, int b, int k, int l, int r)
    {
        //交差しないときはダミー
        if (r <= a || b <= l)
            return dummy;
        if (a <= l && r <= b)
            return dat[k];
        else {
            T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
            T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
            return func(vl, vr);
        }
    }
    T get(int a)
    {
        return query(a, a + 1, 0, 0, n);
    }
};

template <class T>
struct hldec {
    int n;
    int col = 0;
    vector<vector<int>> e;
    vector<vector<int>> heavy;
    vector<vector<int>> light;
    vector<vector<T>> cls;
    vector<T> vers;
    vector<pair<int, int>> pos;
    vector<pair<int, int>> par;
    map<pair<int, int>, int> dict;
    function<T(T, T)> f;
    T unit;
    vector<segtree<T>> vec_seg;
    int root = 0;
    vector<int> size;
    hldec(int n, vector<T> vers, function<T(T, T)> f, T unit, int root = 0) : n(n), root(root), vers(vers), unit(unit), f(f)
    {
        e.assign(n, {});
        par.assign(n, make_pair(-1, -1));
        heavy.assign(n, {});
        light.assign(n, {});
        size.assign(n, 0);
        pos.assign(n, make_pair(-1, -1));
        cls.assign(n, {});
    }
    void add(int u, int v)
    {
        e[u].push_back(v);
        e[v].push_back(u);
    }
    int sub_tree_size(int cur, int par)
    {
        int tmp = 1;
        for (auto s : e[cur]) {
            if (par != s) {
                tmp += sub_tree_size(s, cur);
            }
        }
        size[cur] = tmp;
        return tmp;
    }
    void dfs_label(int cur, int par)
    {
        lli idx = -1;
        lli mem = 0;
        rep(i, e[cur].size())
        {
            auto s = e[cur][i];
            if (s != par) {
                if (size[s] > mem) {
                    mem = size[s];
                    idx = i;
                }
            }
        }
        if (idx == -1)
            return;
        rep(i, e[cur].size())
        {
            auto s = e[cur][i];
            if (s != par) {
                if (idx == i) {
                    heavy[cur].push_back(s);
                } else {
                    light[cur].push_back(s);
                }
                dfs_label(s, cur);
            }
        }
    }
    void edge_labeling()
    {
        sub_tree_size(root, -1);
        dfs_label(root, -1);
    }
    void dfs_arrays(int cur, int c)
    {
        cls[c].push_back(vers[cur]);
        int idx = cls[c].size() - 1;
        pos[cur] = make_pair(c, cls[c].size() - 1);
        dict[pos[cur]] = cur;

        for (auto s : heavy[cur]) {
            dfs_arrays(s, c);
        }
        for (auto s : light[cur]) {
            col++;
            par[col] = make_pair(c, idx);
            dfs_arrays(s, col);
        }
    }
    void make_arrays()
    {
        dfs_arrays(root, 0);
    }
    void build_segtree()
    {
        rep(j, cls.size())
        {
            auto& s = cls[j];
            int size = s.size();
            segtree<T> seg(size, f, unit);
            rep(i, size)
            {
                seg.update(i, s[i]);
            }
            vec_seg.push_back(seg);
        }
    }
    void build(bool opt = false)
    {
        edge_labeling();
        if (opt) {
            e.clear();
        }
        cerr << "labeled done" << endl;
        make_arrays();

        cerr << "arrays" << endl;
        if (opt) {
            heavy.clear();
            light.clear();
        }

        build_segtree();

        cerr << "seg_build" << endl;
    }
    T query(int u, int v)
    {
        vector<pair<int, int>> hist_u;
        vector<pair<int, int>> hist_v;
        rep(j, 2)
        {
            int tmp = j == 1 ? u : v;
            while (true) {
                int cur_col = pos[tmp].first;
                if (j)
                    hist_u.push_back(pos[tmp]);
                else
                    hist_v.push_back(pos[tmp]);
                tmp = dict[par[cur_col]];
                if (cur_col == 0)
                    break;
            }
        }
        int cnt = 0;
        T ans = unit;
        while (true) {
            int idx_u = hist_u.size() - cnt - 1;
            int idx_v = hist_v.size() - cnt - 1;
            if (hist_u[idx_u].first == hist_v[idx_v].first) {
                int r = max(hist_u[idx_u].second, hist_v[idx_v].second) + 1;
                int l = min(hist_u[idx_u].second, hist_v[idx_v].second);
                ans = f(vec_seg[hist_u[idx_u].first].query(l, r), ans);
                break;
            }
            cnt++;
        }
        rep(i, hist_u.size() - cnt - 1)
        {
            ans = f(vec_seg[hist_u[i].first].query(0, hist_u[i].second + 1), ans);
        }
        rep(i, hist_v.size() - cnt - 1)
        {
            ans = f(vec_seg[hist_v[i].first].query(0, hist_v[i].second + 1), ans);
        }
        return ans;
    }
};
vector<pair<lli, lli>> e[4005];
vector<pair<lli, lli>> ne[4005];
int main()
{
    int n, m;
    cin >> n >> m;
    int a, b;
    lli c;
    rep(i, m)
    {
        cin >> a >> b >> c;
        a--, b--;
        e[a].push_back(make_pair(b, c));
        e[b].push_back(make_pair(a, c));
    }
    using p = pair<lli, pair<lli, lli>>;
    priority_queue<p, vector<p>, greater<p>> que;
    bool used[4005] = {};
    que.push(make_pair(0, make_pair(0, -1)));
    lli ans = 0;
    int hoge = n;
    vector<pair<lli, lli>> edge;
    vector<lli> v(2 * n, 0);
    while (!que.empty()) {
        auto cur = que.top().second;
        auto cost = que.top().first;
        que.pop();
        if (used[cur.first])
            continue;
        used[cur.first] = true;
        ans += cost;
        if (cur.second != -1) {
            edge.push_back(make_pair(cur.first, hoge));
            edge.push_back(make_pair(cur.second, hoge));
            v[hoge] = cost;
            hoge++;
        }
        for (auto s : e[cur.first]) {
            que.push(make_pair(s.second, make_pair(s.first, cur.first)));
        }
    }

    auto f = [](lli u, lli v) -> lli { return max(u, v); };
    hldec<lli> tr(hoge, v, f, 0);
    for (auto s : edge) {
        tr.add(s.first, s.second);
    }
    // tr.add(0, 1);
    // tr.add(0, 2);
    // tr.add(1, 3);
    // tr.add(1, 4);
    tr.build(true);
    int s, t, q;
    cin >> q;
    rep(i, q)
    {
        cin >> s >> t;
        cout << ans - tr.query(s - 1, t - 1) << endl;
    }
    // //cout << tr.query(0,1)<<endl;
    // cout << tr.query(3, 4) << endl;
};
;