This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
/*
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
*/
using namespace std;
// using namespace __gnu_pbds;
using namespace chrono;
// mt19937 rng((int) std::chrono::steady_clock::now().time_since_epoch().count());
/*
template <class T> using ordered_set = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>;
*/
//***************** CONSTANTS *****************
const int MXN = 100000;
const int MXM = 500000;
const int INF = 1000000000;
const int MXK = 25;
//***************** GLOBAL VARIABLES *****************
vector<array<int, 2>> g[MXN];
array<int, 2> edges[MXM];
int d[MXN], c, timer, info[2*MXN], tin[2*MXN], tout[2*MXN], up[MXK][2*MXN];
vector<int> ng[2*MXN];
//***************** AUXILIARY STRUCTS *****************
struct UFDS{
vector<int> e;
UFDS(int n){
e.resize(2*n, -1);
}
int get(int x){
return e[x] < 0 ? x : e[x] = get(e[x]);
}
bool unite(int x, int y, int w){
x = get(x), y = get(y);
if(x == y)
return 0;
ng[c].push_back(x);
ng[c].push_back(y);
e[c] = e[x] + e[y];
e[x] = e[y] = c;
info[c] = w;
c++;
return 1;
}
};
void dfs(int u, int p){
tin[u] = timer++;
up[0][u] = p;
for(int i = 1; i < MXK; i++)
up[i][u] = up[i-1][up[i-1][u]];
for(int v : ng[u]) if(v != p) dfs(v, u);
tout[u] = timer;
}
bool isAncestor(int u, int v){
return tin[u] <= tin[v] && tout[u] >= tout[v];
}
int mxpath(int x, int y){
for(int i = MXK - 1; i >= 0; --i){
if(!isAncestor(up[i][x], y))
x = up[i][x];
}
return info[up[0][x]];
}
//***************** MAIN BODY *****************
void solve(){
int N, M;
cin >> N >> M;
c = N;
for(int i = 0; i < M; i++){
int u, v, w;
cin >> u >> v >> w;
--u, --v;
g[u].push_back({v, w});
g[v].push_back({u, w});
edges[i] = {u, v};
}
for(int i = 0; i < N; i++)
d[i] = INF;
priority_queue<array<int, 2>, vector<array<int, 2>>, greater<array<int, 2>>> pq;
int K;
cin >> K;
for(int i = 0; i < K; i++){
int u;
cin >> u;
--u;
d[u] = 0;
pq.push({0, u});
}
while(!pq.empty()){
auto [dis, u] = pq.top();
pq.pop();
if(dis > d[u])
continue;
for(auto& [v, w] : g[u])
if(d[v] > d[u] + w){
d[v] = d[u] + w;
pq.push({d[v], v});
}
}
sort(edges, edges + M, [&](array<int, 2>& a, array<int, 2>& b){
return min(d[a[0]], d[a[1]]) > min(d[b[0]], d[b[1]]);
});
UFDS D(N);
for(int i = 0; i < M; i++){
auto [u, v] = edges[i];
int w = min(d[u], d[v]);
D.unite(u, v, w);
}
dfs(2*N - 2, 2*N - 2);
int Q;
cin >> Q;
while(Q--){
int u, v;
cin >> u >> v;
--u, -- v;
cout << mxpath(u, v) << '\n';
}
}
/*
multisource dijkstra to find dangerousness of individual components
1. assign every edge a new weight => min dangerousness of either node it connects to
make a reach tree, binary lifting to solve
*/
//***************** *****************
int32_t main(){
ios_base::sync_with_stdio(NULL);
cin.tie(NULL);
#ifdef LOCAL
auto begin = high_resolution_clock::now();
#endif
int tc = 1;
// cin >> tc;
for (int t = 0; t < tc; t++)
solve();
#ifdef LOCAL
auto end = high_resolution_clock::now();
cout << fixed << setprecision(4);
cout << "Execution Time: " << duration_cast<duration<double>>(end - begin).count() << "seconds" << endl;
#endif
return 0;
}
/*
If code gives a WA, check for the following :
1. I/O format
2. Are you clearing all global variables in between tests if multitests are a thing
3. Can you definitively prove the logic
*/
# | 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... |