Submission #1279441

#TimeUsernameProblemLanguageResultExecution timeMemory
1279441enxiayyLOSTIKS (INOI20_lostiks)C++20
100 / 100
1131 ms235204 KiB
#include <bits/stdc++.h>

using namespace std;

#define REP(i, l, r) for(int i = (l); i < (r); ++i)
#define FOR(i, l, r) for(int i = (l); i <= (r); ++i)
#define FORD(i, r, l) for(int i = (r); i >= (l); --i)
#define ff first
#define ss second
#define eb emplace_back
#define pb push_back
#define all(x) x.begin(), x.end()
#define sz(v) (int)v.size()
#define compact(v) v.erase(unique(all(v)), v.end())
#define dbg(v) "[" #v " = " << (v) << "]"
#define el "\n"

using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;

template<class T> bool minimize(T& a, const T& b){ if(a > b) return a = b, true; return false; }
template<class T> bool maximize(T& a, const T& b){ if(a < b) return a = b, true; return false; }

mt19937_64 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
long long randRange(long long l, long long r){ return uniform_int_distribution<long long>(l,r)(rng); }

const int N = 1e6 + 5;
const int LOG = 20;

struct locked_route {
	int u, v, h, id;

	locked_route(int u = 0, int v = 0, int h = 0, int id = 0) : u(u), v(v), h(h), id(id) {}
};

int n, m, s, t;
vector<pii> adj[N];
vector<locked_route> lkr;

namespace HLD {
	int tin[N], tout[N], id[N], siz[N], high[N], dist[N], par[N], head[N], timer_dfs = 0, cur_chain = 0;

	void dfs(int u) {
		siz[u] = 1;
		tin[u] = ++timer_dfs;
		for(auto [v, w] : adj[u]) {if (v == par[u]) continue;
			high[v] = high[u] + 1;
			dist[v] = dist[u] ^ w;
			par[v] = u;
			dfs(v);
			siz[u] += siz[v];
		}
		tout[u] = timer_dfs;
	}

	void dfs2(int u) {
		if (head[cur_chain] == 0) {
			head[cur_chain] = u;
		}
		id[u] = cur_chain;
		int fat = 0;
		for(auto [v, w] : adj[u]) { if (v == par[u]) continue;
			if (siz[fat] < siz[v]) {
				fat = v;
			}
		}
		if (fat != 0) dfs2(fat);

		for(auto [v, w] : adj[u]) {
			if (v == par[u] || v == fat) continue;
			++cur_chain;
			dfs2(v);
		}
	}

	int get_lca(int u, int v) {
		while(id[u] != id[v]) {
			if (id[u] < id[v]) swap(u, v);
			u = par[head[id[u]]];
		}
		return (high[u] < high[v] ? u : v);
	}

	void preapre_lca() {
		dfs(1);
		dfs2(1);
	}

	int get_dist(int u, int v) {
		return high[u] + high[v] - 2 * high[get_lca(u, v)];
	}

	int get_locked(int u, int v) {
		return dist[u] ^ dist[v];
	}
} using namespace HLD;

bool is_sub(int v, int acs) {
	return tin[acs] <= tin[v] && tout[v] <= tout[acs];
}

int key[N], target[N];
ll dp[20][(1 << 20)];

bool can_go(int u, int v, int mask) {
	int sub = get_locked(u, v);
	return ((sub & mask) == sub);
}

void solve() {
	cin >> n >> s >> t;
	FOR(i, 1, n - 1) {
		int u, v, h;
		cin >> u >> v >> h;
		int w = 0;
		if (h != 0) {
			w = (1 << sz(lkr));
			lkr.eb(u, v, h, sz(lkr));
			++m;
		}
		adj[u].eb(v, w);
		adj[v].eb(u, w);

 	}

	preapre_lca();

	if (can_go(s, t, 0)) {
		cout << get_dist(s, t) << el;
		return;
	}


	for(auto _ : lkr) {
		int u = _.u;
		int v = _.v;
		int h = _.h;
		int id = _.id;

		key[id] = h;
		if (high[u] > high[v]) swap(u, v);
		target[id] = (is_sub(s, v) ? v : u);
	}

	FOR(i, 0, m - 1) {
		REP(mask, 0, (1 << m))
			dp[i][mask] = LLONG_MAX;
	}


	FOR(i, 0, m - 1) {
		if (can_go(s, key[i], 0) && can_go(key[i], target[i], 0)) {
			dp[i][(1 << i)] = get_dist(s, key[i]) + get_dist(key[i], target[i]);
		}
	}

	ll ans = LLONG_MAX;
	REP(mask, 0, (1 << m)) {
		FOR(i, 0, m - 1) {
			if (dp[i][mask] == LLONG_MAX) continue;

			FOR(j, 0, m - 1) {
				if (!(mask >> j & 1)) {
					if (can_go(target[i], key[j], mask) &&
						can_go(key[j], target[j], mask)) {
							minimize(dp[j][mask | (1 << j)],
							dp[i][mask] + get_dist(target[i], key[j])
										+ get_dist(key[j], target[j]));
						}
				}
			}

			if (can_go(target[i], t, mask)) {
				minimize(ans, dp[i][mask] + get_dist(target[i], t));
			}
		}
	}

	cout << (ans == LLONG_MAX ? -1 : ans) << el;
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);

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

	return 0;
}

/*

*/

Compilation message (stderr)

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