#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pl;
typedef pair<int,int> pii;
typedef tuple<int,int,int> tpl;
#define all(a) a.begin(), a.end()
#define filter(a) a.erase(unique(all(a)), a.end())
const int mn = 1e5 + 5;
vector<pl> adj[mn];
ll dist[mn], n;
bool vis[mn];
void dijkstra (const vector<int> &sources) {
for (int i = 1; i <= n; i++)
dist[i] = LLONG_MAX, vis[i] = 0;
priority_queue<pl> pq;
for (int u : sources)
dist[u] = 0, pq.emplace(0, u);
while (pq.size()) {
int u = pq.top().second; pq.pop();
if (vis[u]) continue;
vis[u] = 1;
for (pl item : adj[u]) {
ll v, w; tie(v, w) = item;
if (dist[u] + w < dist[v]) {
dist[v] = dist[u] + w;
pq.emplace(-dist[v], v);
}
}
}
}
namespace tree {
int spt[mn][17], par[mn], chain[mn], sz[mn], depth[mn], num[mn], timeDfs;
vector<int> adj[mn];
int szDfs (int u, int p) {
sz[u] = 1;
for (int v : adj[u])
if (v != p) sz[u] += szDfs(v, u);
return sz[u];
}
void dfs (int u, int p, int d, bool toP) {
if (u == 1) szDfs(u, p);
num[u] = ++timeDfs, par[u] = p, depth[u] = d;
chain[u] = (toP ? chain[p] : u);
sort(all(adj[u]), [&] (int a, int b) {
return sz[a] > sz[b];
});
bool heavy = 1;
for (int v : adj[u])
if (v != p) dfs(v, u, d + 1, heavy), heavy = 0;
}
int rmq (int l, int r) {
int p = 31 - __builtin_clz(r - l + 1);
return min(spt[l][p], spt[r - (1 << p) + 1][p]);
}
int query (int a, int b) {
int ans = INT_MAX;
while (chain[a] != chain[b]) {
int ap = par[chain[a]], bp = par[chain[b]];
if (depth[ap] == depth[bp]) {
ans = min(ans, rmq(num[chain[a]], num[a])), a = ap;
ans = min(ans, rmq(num[chain[b]], num[b])), b = bp;
}
else if (depth[ap] > depth[bp])
ans = min(ans, rmq(num[chain[a]], num[a])), a = ap;
else if (depth[bp] > depth[ap])
ans = min(ans, rmq(num[chain[b]], num[b])), b = bp;
}
if (depth[a] > depth[b]) swap(a, b);
return min(ans, rmq(num[a], num[b]));
}
void process() {
dfs(1, 0, 1, 0);
for (int i = 1; i <= n; i++) spt[num[i]][0] = dist[i];
for (int s = 1; (1 << s) <= n; s++) {
for (int i = 1; i + (1 << s) - 1 <= n; i++) {
int p = s - 1;
spt[i][s] = min(spt[i][p], spt[i + (1 << p)][p]);
}
}
}
void addEdge (int a, int b) {
adj[a].push_back(b);
adj[b].push_back(a);
}
};
struct DSU {
vector<int> lab;
DSU (int sz) : lab(sz + 1, -1) {}
int get (int u) {
if (lab[u] < 0) return u;
return lab[u] = get(lab[u]);
}
bool unite (int a, int b) {
a = get(a), b = get(b);
if (a == b) return 0;
if (-lab[a] < -lab[b]) swap(a, b);
lab[a] += lab[b], lab[b] = a;
return 1;
}
};
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int m; cin >> n >> m;
for (int i = 0; i < m; i++) {
int a, b, c; cin >> a >> b >> c;
adj[a].emplace_back(b, c);
adj[b].emplace_back(a, c);
}
int k; cin >> k;
vector<int> sources(k), ord(n);
for (int &u : sources) cin >> u;
dijkstra(sources);
for (int i = 1; i <= n; i++) ord[i - 1] = i;
sort(all(ord), [&] (int a, int b) { return dist[a] > dist[b]; });
vector<bool> added(n + 1);
DSU dsu(n);
for (int u : ord) {
added[u] = 1;
for (pl item : adj[u]) {
int v = item.first;
if (added[v] && dsu.unite(u, v)) tree::addEdge(u, v);
}
}
tree::process();
int q; cin >> q;
while (q--) {
int u, v; cin >> u >> v;
cout << tree::query(u, v) << "\n";
}
return 0;
}
# | 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... |