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: Accepted)

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

#define rep(i,x,y) for(int i=(x);i<(y);++i)
#define debug(x) #x << "=" << (x)

#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define print(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define print(x)
#endif

const int inf=1e9;
const int64_t inf64=1e18;
const double eps=1e-9;

template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec){
    os << "[";
    for (const auto &v : vec) {
    	os << v << ",";
    }
    os << "]";
    return os;
}

class union_find{
	private:
	vector<int> parent,rank,gs;
    int size;
	public:
    int count_group;
    union_find()=default;
    union_find(int n){ init(n); }
    void init(int n){
		size=n;
		count_group=n;
		parent.resize(size);
		rank.assign(size,0);
        gs.assign(size,1);
		for(int i=0; i<size; ++i) parent[i]=i;
	}
	int find(int x){
		if(parent[x]==x) return x;
		else return parent[x]=find(parent[x]);
	}
	void unite(int x,int y){
		x=find(x);
		y=find(y);
		if(x==y) return;
		if(rank[x]<rank[y]){
			parent[x]=y;
            gs[y]+=gs[x];
		} else {
			parent[y]=x;
            gs[x]+=gs[y];
			if(rank[x]==rank[y]) ++rank[x];
		}
		--count_group;
	}
	bool is_same_group(int x,int y){
		return find(x)==find(y);
	}
    int group_size(int x){
        return gs[find(x)];
    };
};

struct edge{
    int from,to,cost;
    bool operator<(const edge& other)const{
        return cost<other.cost;
    }
};

void solve(){
    int n,m;
    cin >> n >> m;
    vector<edge> edges;
    rep(i,0,m){
        int a,b,c;
        cin >> a >> b >> c;
        --a;
        --b;
        edges.push_back(edge({a,b,c}));
    }
    sort(edges.begin(),edges.end());

    union_find uf(n);
    vector<bool> use(m);
    int64_t sum_cost=0;
    rep(i,0,m){
        edge &e=edges[i];
        if(uf.is_same_group(e.to,e.from)) continue;
        uf.unite(e.to,e.from);
        sum_cost+=e.cost;
        use[i]=true;
    }

    vector<vector<pair<int,int>>> graph(n);
    rep(i,0,m){
        if(!use[i]) continue;
        print(edges[i].from+1);
        print(edges[i].to+1);
        graph[edges[i].from].push_back(make_pair(edges[i].to,edges[i].cost));
        graph[edges[i].to].push_back(make_pair(edges[i].from,edges[i].cost));
    }

    vector<vector<int>> max_cost(n,vector<int>(n));
    vector<bool> done(n);
    function<void(int,int,int)> dfs=[&](int s,int u,int ma){
        done[u]=true;
        max_cost[s][u]=ma;
        for(auto &p:graph[u]){
            if(done[p.first]) continue;
            dfs(s,p.first,max(ma,p.second));
        }
        done[u]=false;
    };
    rep(i,0,n) dfs(i,i,0);
    rep(i,0,n){
        print(i+1);
        rep(j,0,n){
            print(j+1);
            print(max_cost[i][j]);
        }
    }
    int q;
    cin >> q;
    rep(i,0,q){
        int s,t;
        cin >> s >> t;
        --s;
        --t;
        cout << sum_cost-max_cost[s][t] << endl;
    }
}

int main(){
    std::cin.tie(0);
    std::ios::sync_with_stdio(false);
    cout.setf(ios::fixed);
    cout.precision(10);
    solve();
    return 0;
}