Submission #567473

#TimeUsernameProblemLanguageResultExecution timeMemory
567473_karan_gandhiValley (BOI19_valley)C++17
100 / 100
314 ms60176 KiB
#include <bits/stdc++.h>
using namespace std;

#define all(v) v.begin(), v.end()
#define endl '\n'
#define pl(var) " [" << #var << ": " << (var) << "] "
#define ll long long

template<typename A, typename B> ostream& operator<<(ostream &cout, pair<A, B> const &p) { return cout << "[" << p.first << ", " << p.second << "]"; }
template<typename A> ostream& operator<<(ostream &cout, vector<A> const &v) { cout << "["; for(int i = 0; i < (int)v.size(); i++) {if (i) cout << ", "; cout << v[i];} return cout << "]";}
template<typename A, typename B> istream& operator>>(istream& cin, pair<A, B> &p) { cin >> p.first; return cin >> p.second; }

vector<vector<pair<int, int>>> adj;
vector<int> tin, tout, par, dep;
vector<ll int> dist, dp1, dp2;
vector<bool> shop;
int timer = 0;

void dfs(int u, int p, ll int dis, int d = 0) {
	dist[u] = dis;
	tin[u] = timer++;
	par[u] = p;
	dep[u] = d;

	for (auto [v, w] : adj[u]) {
		if (v == p) continue;

		dfs(v, u, dis + w, d + 1);
	}

	if (shop[u]) dp1[u] = dist[u];
	else dp1[u] = 1e18;

	for (auto [v, wt] : adj[u]) {
		if (v == p) continue;

		dp1[u] = min(dp1[u], dp1[v]);
	}

	tout[u] = timer - 1;
}

bool is_acc(int acc, int child) {
	if (acc == child) return 1;
	return tin[acc] < tin[child] && tin[child] <= tout[acc];
}

void solve() {
	int n, s, q, e; cin >> n >> s >> q >> e;

	adj.resize(n);
	dp1.resize(n);
	dp2.resize(n);
	tin.resize(n);
	tout.resize(n);
	dist.resize(n);
	shop.resize(n);
	par.resize(n);
	dep.resize(n);

	fill(all(dp1), 1e18);

	vector<pair<pair<int, int>, int>> edges;

	for (int i = 0; i < n - 1; i++) {
		int a, b; cin >> a >> b;
		int c; cin >> c;
		a--, b--;

		adj[a].emplace_back(b, c);
		adj[b].emplace_back(a, c);
		edges.emplace_back(make_pair(a, b), c);
	}

	for (int i = 0; i < s; i++) {
		int a; cin >> a;
		shop[a - 1] = 1;
	}

	// e is the root
	dfs(e - 1, e - 1, 0);
	for (int i = 0; i < n; i++) {
		dp1[i] = dp1[i] - 2 * dist[i];
	}

	// eureka!! binary lifting for path queries
	const int LOG = 20;
	vector<vector<ll int>> jumpNode(n, vector<ll int>(20)), jumpDP(n, vector<ll int>(20));

	for (int i = 0; i < n; i++) {
		jumpNode[i][0] = par[i];
		jumpDP[i][0] = dp1[i];
	}

	for (int i = 1; i < LOG; i++) {
		for (int j = 0; j < n; j++) {
			jumpNode[j][i] = jumpNode[jumpNode[j][i - 1]][i - 1];
			jumpDP[j][i] = min(jumpDP[j][i - 1], jumpDP[jumpNode[j][i - 1]][i - 1]); // somewhat like sparse tables
		}
	}

	// cout << jumpDP << endl;

	auto query = [&](int u, int k) -> ll int {
		int pow = LOG;
		ll int res = 1e18;
		// cout << pl(k) << pl(u) << endl;
		// cout << pl(jumpDP[u][0]) << endl;
		while (k > 0) {
			while (k < (1 << pow)) pow--;
			res = min(res, jumpDP[u][pow]);
			// cout << pl(jumpDP[u][pow]) << endl;
			u = jumpNode[u][pow];
			k -= (1 << pow);
		}

		return res;
	};

	while (q--) {
		int a, b; cin >> a >> b;

		a--, b--;
		pair<int, int> edge = edges[a].first;
		if (is_acc(edge.first, b) && is_acc(edge.second, b)) {
			int one = edge.first;
			if (dist[one] < dist[edge.second]) {
				one = edge.second;
			}

			ll int res = query(b, dep[b] - dep[one] + 1);
			// res = min(res, dp1[b]) << endl;
			// cout << pl(dep[one]) << pl(dep[b]) << endl;
			if (res >= 1e16) {
				cout << "oo" << endl;
			} else {
				cout << res + dist[b] << endl;
			}
		} else {
			cout << "escaped" << endl;
		}
	}
}

int main() {
	// freopen(".in", "r", stdin);
	// freopen(".out", "w", stdout);

	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int T = 1;
	// cin >> T;
	while (T--)
		solve();
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...