Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- template<int SZ> struct centroidDecomp {
- int N;
- bool done[SZ];
- int sub[SZ], par[SZ], cen[SZ];
- ll ans[SZ];
- ll dist[SZ][20], tmp[SZ];
- vpi adj[SZ];
- // INITIALIZE
- void addEdge(int a, int b, int d) { adj[a].pb({b,d}), adj[b].pb({a,d}); }
- void dfs (int no) {
- sub[no] = 1;
- for (pi i: adj[no]) if (!done[i.f] && i.f != par[no]) {
- par[i.f] = no;
- dfs(i.f);
- sub[no] += sub[i.f];
- }
- }
- void genDist(int par, int no, int t, ll dis) {
- dist[no][tmp[no]++] = dis;
- for (pi i: adj[no]) if (!done[i.f] && i.f != par) {
- cen[i.f] = t;
- genDist(no,i.f,t,dis+i.s);
- }
- }
- int getCentroid(int x) {
- par[x] = -1; dfs(x);
- int sz = sub[x];
- while (1) {
- pi mx = {0,0};
- for (pi i: adj[x]) if (!done[i.f] && i.f != par[x]) mx = max(mx,{sub[i.f],i.f});
- if (mx.f*2 > sz) x = mx.s;
- else return x;
- }
- }
- void solve (int x) {
- x = getCentroid(x); done[x] = 1;
- genDist(-1,x,x,0);
- for (pi i: adj[x]) if (!done[i.f]) solve(i.f);
- }
- void init() {
- F0R(i,N) cen[i] = -1, ans[i] = INF;
- solve(0);
- }
- // QUERY
- void upd(int v, int x = 1) {
- for (int V = v, ind = tmp[v]-1; V >= 0; V = cen[V], ind --) {
- // cout << "OH " << v << " " << V << " " << x << "\n";
- if (x == 1) ans[V] = min(ans[V],dist[v][ind]);
- else ans[V] = INF;
- }
- }
- ll query(int v) {
- ll ret = INF;
- for (int V = v, ind = tmp[v]-1; V >= 0; V = cen[V], ind --) {
- // cout << "AH " << V << " " << v << "\n";
- ret = min(ret,ans[V]+dist[v][ind]);
- }
- return ret;
- }
- };
- centroidDecomp<MX> C;
- void Init(int N, int A[], int B[], int D[]) {
- C.N = N;
- F0R(i,N-1) C.addEdge(A[i],B[i],D[i]);
- C.init();
- }
- long long Query(int S, int X[], int T, int Y[]) {
- ll ans = INF;
- if (S > T) {
- swap(S,T);
- swap(X,Y);
- }
- F0R(i,S) C.upd(X[i]);
- F0R(i,T) ans = min(ans,C.query(Y[i]));
- F0R(i,S) C.upd(X[i],-1);
- return ans;
- }
Advertisement
Add Comment
Please, Sign In to add comment