Submission #863994

#TimeUsernameProblemLanguageResultExecution timeMemory
863994wiiEvacuation plan (IZhO18_plan)C++17
100 / 100
439 ms39152 KiB
#include <bits/stdc++.h>
using namespace std;

typedef double db;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;

#define X first
#define Y second
#define gcd __gcd
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define bit(i, mask) ((mask) >> (i) & 1)
#define reset(x, val) memset(x, val, sizeof(x))
#define foru(i,a,b) for(int i = (a); i <= (b); ++i)
#define ford(i,a,b) for(int i = (a); i >= (b); --i)
#define FastIO ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

template<typename T> bool maximize(T &res, const T &val) { if (res < val) { res = val; return true; } return false; }
template<typename T> bool minimize(T &res, const T &val) { if (val < res) { res = val; return true; } return false; }

const ll Linf = 0x3f3f3f3f3f3f3f3f;
const int Inf = 0x3f3f3f3f;
const ll Mod = 1e9 + 7;
const ll Mod2 = ll(1e9) + 9;
const int Lim = 1e6 + 5;
const int inv6 = 166666668;

/// ====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====

const int base = 3;
const int N = 1e5 + 2;
const int K = log2(N);
const int dx[] = {+1, -1, 0, 0};
const int dy[] = {0, 0, +1, -1};
const int block_size = sqrt(2e9) + 2;

struct edge {
    int u, v, w;

    edge(int u = 0, int v = 0, int w = 0):
        u(u), v(v), w(w) {}
};

int n, m, k;
int u, v, w;
int d[N];
vector<edge> edges;
vector<int> adj[N];
vector<pii> g[N];

int other(int id, int u) {
    return edges[id].u ^ edges[id].v ^ u;
}

int par[N];
int root(int u) {
    return par[u] == 0 ? u : par[u] = root(par[u]);
} 

int join(int u, int v) {
    if ((u = root(u)) == (v = root(v)))
        return false;
    par[v] = u; return true;
}

int up[N][K + 1], mw[N][K + 1];
int tin[N], tout[N], timer;
void dfs(int u, int p) {    
    tin[u] = ++timer;

    foru(k, 1, K) {
        up[u][k] = up[up[u][k - 1]][k - 1];
        mw[u][k] = min(mw[u][k - 1], mw[up[u][k - 1]][k - 1]);
    }

    for (auto &[v, w]: g[u]) if (v != p) {
        up[v][0] = u;
        mw[v][0] = w;

        dfs(v, u);
    }

    tout[u] = timer;
}

int isanc(int root, int u) {
    return tin[root] <= tin[u] && tout[u] <= tout[root];
}

int lca(int u, int v) {
    if (isanc(u, v)) return u;
    if (isanc(v, u)) return v;

    ford(k, K, 0) if (up[u][k])
        if (!isanc(up[u][k], v))
            u = up[u][k];
    return up[u][0];
}

int query(int u, int v) {
    int ans = min(d[u], d[v]);
    int w = lca(u, v);

    minimize(ans, d[w]);

    ford(k, K, 0) if (up[u][k])
        if (!isanc(up[u][k], w)) {
            minimize(ans, mw[u][k]);
            u = up[u][k];
        }

    u = v;
    ford(k, K, 0) if (up[u][k])
        if (!isanc(up[u][k], w)) {
            minimize(ans, mw[u][k]);
            u = up[u][k];
        }
    
    return ans;
}

void solve() {
    cin >> n >> m;

    foru(i, 1, m) {
        cin >> u >> v >> w;

        adj[u].pb(edges.size());
        adj[v].pb(edges.size());
        edges.emplace_back(u, v, w);
    }

    priority_queue<pii> q;
    foru(i, 1, n) d[i] = Inf;

    cin >> k;
    foru(i, 1, k) cin >> u, d[u] = 0, q.push({0, u});

    while (!q.empty()) {
        auto [w, u] = q.top(); q.pop(); w = -w;

        if (d[u] != w) continue;
        for (int id: adj[u]) {
            int v = other(id, u);

            if (minimize(d[v], d[u] + edges[id].w))
                q.emplace(-d[v], v);
        }
    }

    for (auto &[u, v, w]: edges)
        w = min(d[u], d[v]);
    
    sort(all(edges), [&](const edge &x, const edge &y){
        return x.w > y.w;
    });

    for (auto &[u, v, w]: edges)
        if (join(u, v)) {
            g[u].pb({v, w});
            g[v].pb({u, w});
        }
    
    dfs(1, 0);

    int qs; cin >> qs; 
    while (qs--) {
        cin >> u >> v;
        cout << query(u, v) << "\n";
    }
}

signed main() {
    FastIO;

    #define task "test"
    if (fopen(task".inp", "r")) {
		freopen(task".inp", "r", stdin);
		freopen(task".out", "w", stdout);
	}

    int ntest = 1;
    // cin >> ntest;
    while (ntest--) {
        //cout << "Case " << q << ": " << "\n"; 
        solve();
        cout << "\n";
    }

    return 0;
}

/**  /\_/\
 *  (= ._.)
 *  / >TL \>AC
**/

Compilation message (stderr)

plan.cpp: In function 'int main()':
plan.cpp:180:10: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  180 |   freopen(task".inp", "r", stdin);
      |   ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
plan.cpp:181:10: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  181 |   freopen(task".out", "w", stdout);
      |   ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...