Submission #1213272

#TimeUsernameProblemLanguageResultExecution timeMemory
1213272minhpkValley (BOI19_valley)C++20
100 / 100
277 ms104596 KiB
#include <bits/stdc++.h>
#define int long long
using namespace std;

const int MAXN = 100005;
const int INF = 1e17;


vector<pair<int,int>> z[MAXN];
pair<int,int> canh[MAXN];
int high[MAXN];
int low[MAXN];
int check[MAXN];
int up[MAXN][25];
int g[MAXN][25];
int val[MAXN][25];
int sta[MAXN];
int fin[MAXN];
int rev[MAXN];
int tour;
int a, s, q, e;
int down[MAXN][25];
int dis[MAXN];
int fwd[25];

struct node{
    pair<int,int> st,nd,rd;
};
node low1[1000000];


void update(int i,int val,int p){
    if (val<=low1[i].st.first){
        low1[i].rd=low1[i].nd;
        low1[i].nd=low1[i].st;
        low1[i].st={val,p};
    }else if (val<=low1[i].nd.first){
        low1[i].rd=low1[i].nd;
        low1[i].nd={val,p};
    }else if (val<=low1[i].rd.first){
        low1[i].rd={val,p};
    }
}



void dfs(int i, int par) {
    tour++;
    sta[i] = tour;
    rev[tour] = i;
    low[i] = INF;
    if (check[i]) {
        low[i] = 0;
        update(i,0,i);
    }
    for (auto p : z[i]) {
        if (p.first == par) continue;
        high[p.first] = high[i] + 1;
        dis[p.first] = dis[i] + p.second;
        dfs(p.first, i);
        update(i,low[p.first]+p.second,p.first);
        low[i] = min(low[i], low[p.first] + p.second);
    }
    fin[i] = tour;
}

void dfs1(int i, int par) {
    up[i][0] = par;
    for (int j = 1; j <= 20; j++) {
        up[i][j] = up[up[i][j - 1]][j - 1];
        g[i][j] = g[up[i][j - 1]][j - 1] + g[i][j - 1];
        val[i][j] = min(val[i][j - 1], val[up[i][j - 1]][j - 1] + g[i][j - 1]);
        down[i][j] = min(down[i][j - 1], down[up[i][j - 1]][j - 1]);
    }
    int max1 = INF, max2 = INF;
    int trace = 0, id = 0;
    if (check[i]) {
        max1 = 0;
        trace = 0;
        id = 0;
    }
    for (auto p : z[i]) {
        if (p.first == par) continue;
        if (max1 > low[p.first] + p.second) {
            max1 = low[p.first] + p.second;
            trace = p.first;
            id = p.second;
        }
    }
    for (auto p : z[i]) {
        if (p.first == par) continue;
        if (p.first == trace) continue;
        if (max2 > low[p.first] + p.second) {
            max2 = low[p.first] + p.second;
        }
        g[p.first][0] = p.second;
        val[p.first][0] = p.second + max1;
        down[p.first][0] = max1 + dis[i];
        dfs1(p.first, i);
    }
    if (trace) {
        g[trace][0] = id;
        val[trace][0] = id + max2;
        down[trace][0] = max2 + dis[i];
        dfs1(trace, i);
    }
}
int lca(int x,int y){
   if (high[x]<high[y]){
       swap(x,y);
   }

   for (int i=20;i>=0;i--){
       if (high[up[x][i]]>=high[y]){
           x=up[x][i];
       }
   }
 //  cout << x << " " << y << '\n';
   if (x==y){
       return x;
   }

   for (int i=20;i>=0;i--){
       if (up[x][i]!=up[y][i] && up[x][i]!=0){
           x=up[x][i];
           y=up[y][i];
       }
   }
   return up[x][0];
}

int caldis(int x,int y){
    if (high[x]<high[y]){
        swap(x,y);
    }
    int cnt=0;
    for (int i=20;i>=0;i--){
         if (high[up[x][i]]>=high[y]){
             cnt+=g[x][i];
             x=up[x][i];
         }
    }
    if (x==y){
        return cnt;
    }
    for (int i=20;i>=0;i--){
       if (up[x][i]!=up[y][i] && up[x][i]!=0){
           cnt+=g[x][i];
           cnt+=g[y][i];

           x=up[x][i];
           y=up[y][i];
       }
   }

   return cnt+g[x][0]+g[y][0];
}

bool check1(int p,int x){
   // cout << sta[x] << " " << fin[x] << "\n";
    bool req1 = (sta[p] >= sta[x] && sta[p] <= fin[x] && sta[e] >= sta[x] && sta[e] <= fin[x]);
    bool req2 = ((sta[p] < sta[x] || sta[p] > fin[x]) && (sta[e] < sta[x] || sta[e] > fin[x]));
    return (req1 || req2);
}


signed main() {
   // freopen("test.txt", "r", stdin);
   // freopen("o2.out", "w", stdout);
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> a >> s >> q >> e;
    fwd[0] = 1;
    for (int i = 1; i <= 20; i++) {
        fwd[i] = fwd[i - 1] * 2;
    }
    for (int i = 1; i < a; i++) {
        int x, y, t;
        cin >> x >> y >> t;
        canh[i] = {x, y};
        z[x].push_back({y, t});
        z[y].push_back({x, t});
    }
    for (int i = 1; i <= s; i++) {
        int x;
        cin >> x;
        check[x] = 1;
    }

    for (int i=1;i<=a;i++){
        low1[i].st={1e17,1};
        low1[i].nd={1e17,1};
        low1[i].rd={1e17,1};
    }
    high[0]=-1;
    dfs(e, 0);
    dfs1(e, 0);



   // for (int i=1;i<=a;i++){
   //     cout << low[i] << "\n";
  //  }
    while (q--) {
        int road, p;
        cin >> road >> p;
        int x = canh[road].first;
        int y = canh[road].second;

        int dis1=caldis(x,p);
        int dis2=caldis(y,p);
        if (dis1>dis2){
            swap(x,y);
        }


       int l=lca(p,x);
       int l1=lca(p,y);

       // cout << x <<  " " << p << "\n";
      //  cout << l << " " << l1 << "\n";
        if (l!=x || l1!=y) {
            cout << "escaped" << "\n";
            continue;
        }

        int ans=INF;
        //cout << sta[x] << " " << sta[p] << "\n";
        if (sta[x]<sta[p] || sta[x]>fin[p]){

            ans=min(ans,low[p]);
            //cout << "ok" << "\n";
        }
       // cout << ans << "\n";
        if (check[p]){
            ans=0;
        }
        int pos1,pos2;

        int distance = high[p] - high[l]-1;
        int t_node = p;
        int cur = 0;
        int step = 0;
        for (int i = 20; i >= 0; i--) {
            if (step + fwd[i] <= distance) {
                    ans = min(ans, val[t_node][i] + cur);
                    cur += g[t_node][i];
                    t_node = up[t_node][i];
                    step += fwd[i];
            }
        }
        pos1=t_node;
        if (pos1==l){
            pos1=-1;
        }
         distance = high[x] - high[l]-1;
         t_node = x;
         cur = 0;
         step = 0;
        for (int i = 20; i >= 0; i--) {
            if (step + fwd[i] <= distance) {
                    ans = min(ans, down[t_node][i] -dis[l] + (dis[p]-dis[l]));

                    t_node = up[t_node][i];
                    step += fwd[i];
            }
        }
        pos2=t_node;
        if (x==l){
            pos2=-1;
        }
       // cout << pos1 << " " << pos2 << "\n";
        int preans;
        if (low1[l].st.second==pos1 ||low1[l].st.second==pos2 ){
            if (low1[l].nd.second==pos1 || low1[l].nd.second==pos2){
               // cout << "ok" << "\n";
                preans=low1[l].rd.first+dis[p]-dis[l];
            }else{
                //cout << "ok" << "\n";
                preans=low1[l].nd.first+dis[p]-dis[l];
            }
        }else{
               // cout << "ok" << " ";
              //  cout << low1[l].st.first << "\n";
              //  cout << "ok" << "\n";
                preans=low1[l].st.first+dis[p]-dis[l];
        }

        // cout << preans << "\n";
        ans=min(ans,preans);
        if (sta[p]<sta[x] || sta[p]>fin[x]){
            int distance = high[1] - high[l];
            int t_node = l;
            int cur = 0;
            int step = 0;
            for (int i = 20; i >= 0; i--) {
               if (step + fwd[i] <= distance) {
                    ans = min(ans, val[t_node][i] + cur);
                    cur += g[t_node][i];
                    t_node = up[t_node][i];
                    step += fwd[i];
               }
            }
        }


        if (ans>=INF){
            cout << "oo" << "\n";
        }else{
            cout << ans << "\n";
        }


    }
    return 0;
}


/*
freopen("test.txt", "r", stdin);
    freopen("o2.out", "w", stdout);
*/

/*
10 3 2 2
1 1 0
1 1 0
0 1 1
1 0 0
1 1 0
1 0 1
1 0 1
1 1 0
0 0 1
0 1 1
0
0
*/
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...