# | 제출 시각 | 아이디 | 문제 | 언어 | 결과 | 실행 시간 | 메모리 |
---|---|---|---|---|---|---|---|
305900 | limabeans | 공장들 (JOI14_factories) | C++17 | 0 ms | 0 KiB |
이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include "factories.h"
#include <bits/stdc++.h>
using namespace std;
template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl
using ll = long long;
const ll inf = 1e18;
const int maxn = 5e5 + 100;
const int LOG = 20;
int n;
vector<pair<ll,int>> g[maxn];
int par[LOG+1][maxn];
int dep[maxn];
ll len[maxn];
void dfs(int at, int p) {
for (int j=1; j<LOG; j++) {
par[j][at] = par[j-1][par[j-1][at]];
}
for (auto ed: g[at]) {
ll wei = ed.first;
int to = ed.second;
if (to == p) continue;
dep[to] = 1+dep[at];
len[to] = len[at] + wei;
par[0][to] = at;
dfs(to, at);
}
}
int lca(int u, int v) {
if (dep[u]<dep[v]) swap(u, v);
int dx = dep[u]-dep[v];
for (int j=0; j<LOG; j++) {
if (dx>>j&1) {
u = par[j][u];
}
}
if (u == v) return u;
for (int j=LOG-1; j>=0; j--) {
if (par[j][u] != par[j][v]) {
u = par[j][u];
v = par[j][v];
}
}
return par[0][u];
}
ll dist(int u, int v) {
int mid = lca(u, v);
return len[u] + len[v] - 2ll*len[mid];
}
vector<int> ctree[maxn];
bool bad[maxn];
int siz[maxn];
void dfs2(int at, int p) {
siz[at] = 1;
for (auto ed: g[at]) {
int to = ed.second;
if (!bad[to] && to != p) {
dfs2(to, at);
siz[at] += siz[to];
}
}
}
int findCenter(int at) {
dfs2(at, -1);
int all = siz[at];
bool ok = true;
while (ok) {
ok = false;
for (auto ed: g[at]) {
int to = ed.second;
if (bad[to]) continue;
if (siz[to] > siz[at]) continue;
if (siz[to]*2 >= all) {
at = to;
ok = true;
break;
}
}
}
return at;
}
int build(int at) {
at = findCenter(at);
bad[at] = true;
for (auto ed: g[at]) {
int to = ed.second;
if (!bad[to]) {
int nc = build(to);
ctree[at].push_back(nc);
ctree[nc].push_back(at);
}
}
return at;
}
int cpar[maxn];
void cdfs(int at, int p, int dep=0) {
assert(dep <= 23);
for (int to: ctree[at]) {
if (to == p) continue;
cpar[to] = at;
cdfs(to, at, dep+1);
}
}
ll nearest[maxn];
void Init(int N, int A[], int B[], int D[]) {
n = N;
for (int i=0; i<n-1; i++) {
int u = A[i];
int v = B[i];
ll d = D[i];
g[u].push_back({d,v});
g[v].push_back({d,u});
}
dfs(0, -1);
int root = build(0);
cpar[root] = -1;
cdfs(root, -1);
for (int i=0; i<n+10; i++) {
nearest[i] = inf;
}
}
long long Query(int S, int X[], int T, int Y[]) {
ll res = inf;
set<int> v;
for (int i=0; i<S; i++) {
int node = X[i];
int at = node;
int iter=0;
while (~at) {
v.insert(at);
nearest[at] = min(nearest[at], dist(node, at));
at = cpar[at];
assert(++iter <= 23);
}
}
for (int i=0; i<T; i++) {
int node = Y[i];
int at = node;
int iter=0;
while (~at) {
v.insert(at);
ll cur = nearest[at] + dist(node, at);
res = min(res, cur);
at = cpar[at];
assert(++iter <= 23);
}
}
for (int x: v) {
nearest[x] = inf;
}
return res;
}
int N, Q;
int A[maxn], B[maxn], D[maxn];
int S, T, X[maxn], Y[maxn];
int main() {
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin>>N>>Q;
for (int i=0; i<N-1; i++) {
cin>>A[i]>>B[i]>>D[i];
}
Init(N, A, B, D);
for (int z=0; z<Q; z++) {
cin>>S>>T;
for (int i=0; i<S; i++) {
cin>>X[i];
}
for (int i=0; i<T; i++) {
cin>>Y[i];
}
cout<<Query(S, X, T, Y)<<endl;
}
return 0;
}