//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx,avx2")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,avx,avx2")
//#pragma GCC optimize("trapv")
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define all(x) x.begin(), x.end()
#define mpr make_pair
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int nmax = 100011, mod = 1000000007, inf = 2000010000, key = 200003, lg = 20, block = 300;
const ll infll = 4000000000000000000;
const ld eps = 1e-9;
int dist[nmax], color[nmax], used[nmax] = {0};
vector<array<int, 2>> graf[nmax];
vector<int> nodes[nmax], query[nmax];
void dickstra(int n) {
set<array<int, 2>> st;
for(int i = 1; i <= n; i++) {
if(dist[i] == 0)
st.insert({0, i});
}
while(!st.empty()) {
auto cur = *st.begin();
st.erase(st.begin());
for(auto i : graf[cur[1]]) {
if(dist[i[0]] > cur[0] + i[1]) {
st.erase({dist[i[0]], i[0]});
dist[i[0]] = cur[0] + i[1];
st.insert({dist[i[0]], i[0]});
}
}
}
return ;
}
void solve()
{
int n, m;
cin >> n >> m;
fill(dist, dist + n + 1, inf);
int u, v, w;
for(int i = 0; i < m; i++) {
cin >> u >> v >> w;
graf[u].pb({v, w});
graf[v].pb({u, w});
}
int k;
//cout << "Need k\n";
cin >> k;
for(int i = 0; i < k; i++) {
cin >> u;
dist[u] = 0;
}
dickstra(n);
vector<array<int, 2>> order(n);
for(int i = 0; i < n; i++) {
order[i] = {dist[i + 1], i + 1};
//cout << i + 1 << " " << dist[i + 1] << " v dist[v]\n";
}
sort(all(order));
reverse(all(order));
int q;
//cout << "Need q\n";
cin >> q;
map<array<int, 2>, int> ans;
vector<array<int, 2>> queries(q);
for(int i = 0; i < q; i++) {
cin >> u >> v;
queries[i] = {u, v};
query[u].pb(v);
query[v].pb(u);
}
//cout << "Done\n";
for(int i = 1; i <= n; i++) {
color[i] = i;
nodes[i].pb(i);
}
int colorv, colorj;
for(int i = 0; i < n; i++) {
v = order[i][1];
used[v] = 1;
//cout << "\n\nCURRENT NODE IS " << v << "\n";
for(auto j : graf[v]) {
if(!used[j[0]] || color[v] == color[j[0]])
continue;
//cout << "current edge: " << v << " " << j[0] << "\n";
colorv = color[v];
colorj = color[j[0]];
if(nodes[colorv].size() < nodes[colorj].size())
swap(colorv, colorj);
//cout << "combine " << colorv << " with " << colorj << "\n";
for(int u : nodes[colorj]) {
//cout << "looking at " << u << "\n";
for(int k : query[u]) {
if(colorv == color[k]) {
//cout << "FOUND ANSWER TO " << u << " " << k << "\n";
ans[{u, k}] = order[i][0];
ans[{k, u}] = order[i][0];
}
}
}
for(int u : nodes[colorj]) {
//cout << u << " is now color " << colorv << "\n";
nodes[colorv].pb(u);
color[u] = colorv;
}
}
}
for(int i = 0; i < q; i++)
cout << ans[{queries[i][0], queries[i][1]}] << "\n";
return ;
}
int main()
{
//freopen("wormsort.in","r",stdin);
//freopen("wormsort.out","w",stdout);
//ios_base::sync_with_stdio(0);cin.tie(0);
srand(8713);
//init();
int t = 1;
//cin >> t;
//int t_ = t;
//t = rdi();
while(t--) {
//cout << "Case #" << t_ - t << ": ";
solve();
}
//flush();
return 0;
}
/*
9 12
1 9 4
1 2 5
2 3 7
2 4 3
4 3 6
3 6 4
8 7 10
6 7 5
5 8 1
9 5 7
5 4 12
6 8 2
2
4 7
5
1 6
5 3
4 8
5 8
1 5
*/
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |