Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma GCC optimize("Ofast")
- #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
- #include <bits/stdc++.h>
- #define f first
- #define s second
- #define mp make_pair
- using namespace std;
- typedef long long ll;
- vector < vector <int> > g;
- vector < vector <int> > tree;
- vector <bool> used;
- map < pair <int, int> , int> edges;
- vector <ll> h;
- vector <int> tin, tout;
- vector < vector <int> > par;
- unordered_map <int, vector <ll> > D;
- int timer = 0;
- void bfs(int v){
- queue <int> q;
- q.push(v);
- used[v] = 1;
- while(!q.empty()){
- v = q.front();
- q.pop();
- for(int i = 0; i < g[v].size(); i++){
- int to = g[v][i];
- if(!used[to]){
- used[to] = 1;
- tree[v].push_back(to);
- tree[to].push_back(v);
- edges[{v, to}] *= -1;
- edges[{v, to}] *= -1;
- q.push(to);
- }
- }
- }
- }
- void init(int n){
- int log_ = 0;
- while((1 << log_) < n)log_++;
- for(int i = 0; i < n; i++)par[i].resize(log_ + 1);
- }
- void dfs(int v, int p){
- tin[v] = timer++;
- par[v][0] = p;
- for(int i = 1; i < par[v].size(); i++)
- par[v][i] = par[par[v][i - 1]][i - 1];
- for(int i = 0; i < tree[v].size(); i++){
- int to = tree[v][i];
- if(to == p)continue;
- h[to] = h[v] + edges[{v, to}];
- dfs(to, v);
- }
- tout[v] = timer++;
- }
- bool upper(int u, int v){
- return (tin[u] <= tin[v] && tout[u] >= tout[v]);
- }
- int lca(int u, int v){
- if(upper(u, v))return u;
- if(upper(v, u))return v;
- for(int i = par[v].size() - 1; i >= 0; i--)
- if(!upper(par[v][i], u))v = par[v][i];
- return par[v][0];
- }
- void D_init(int n){
- for(auto it = edges.begin(); it != edges.end(); it++){
- if(it->s < 0)it->s *= -1;
- else D[it->f.f].resize(n, LLONG_MAX), edges[{it->f.s, it->f.f}] *= -1;
- }
- for(auto it = D.begin(); it != D.end(); it++){
- int i = it->f;
- set < pair <ll, int> > q;
- D[i][i] = 0;
- q.insert({0, i});
- while(!q.empty()){
- int v = q.begin()->s;
- q.erase(q.begin());
- for(int j = 0; j < g[v].size(); j++){
- int to = g[v][j];
- if(D[i][to] > D[i][v] + edges[{v, to}]){
- q.erase({D[i][to], to});
- D[i][to] = D[i][v] + edges[{v, to}];
- q.insert({D[i][to], to});
- }
- }
- }
- }
- }
- ll ans(int u, int v){
- ll mn = LLONG_MAX;
- for(auto it = D.begin(); it != D.end(); it++)
- mn = min(mn, (it->s)[u] + (it->s)[v]);
- return (min(h[u] + h[v] - 2 * h[lca(u, v)], mn));
- }
- int main()
- {
- ios_base::sync_with_stdio(0);
- cin.tie(0);
- int n, m;
- cin >> n >> m;
- g.resize(n), used.resize(n), tree.resize(n), h.resize(n), par.resize(n),
- tin.resize(n), tout.resize(n);
- for(int i = 0; i < m; i++){
- int u, v, d;
- cin >> u >> v >> d;
- u--, v--;
- g[u].push_back(v);
- g[v].push_back(u);
- edges[{u, v}] = d;
- edges[{v, u}] = d;
- }
- bfs(0);
- D_init(n);
- init(n);
- dfs(0, 0);
- int q;
- cin >> q;
- while(q--){
- int u, v;
- cin >> u >> v;
- u--, v--;
- cout << ans(u, v) << '\n';
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement