Submission #825473

#TimeUsernameProblemLanguageResultExecution timeMemory
825473Shreyan_PaliwalValley (BOI19_valley)C++17
0 / 100
2 ms2644 KiB
// #pragma GCC optimize("Ofast")
// #include <bits/stdc++.h>
// using namespace std;

// #define int long long

// const int maxn = 100000;
// const int INF = 2000000000;

// int n, s, q, e; // nodes, numshops, numqueries, valleynode
// vector<pair<int,int>> adj[maxn];
// pair<int,int> edges[maxn];
// int shop[maxn]; // is shop?
// int closest[maxn]; // closest shop in subtree

// int dist[maxn]; // distance to root, set


// int dpth[maxn]; // depth from root, set
// int bl[maxn][20]; // set
// int bld[maxn][20]; // array[nd] = - 2 * dist[nd] + min(dist[shop]) for shop in subtree[dist]


// void dfs(int nd, int par, int pardist, int d) {
//     // set depth
//     dpth[nd] = d;

//     // set binary lifting
//     bl[nd][0] = par;
//     for (int i = 1; i < 20; i++) bl[nd][i] = bl[bl[nd][i-1]][i-1];

//     // recurse dfs, set distance from root
//     for (auto i : adj[nd])
//         if (i.first != par) {
//             dist[i.first] = dist[nd] + i.second;    
//             dfs(i.first, nd, i.second, d+1);
//         }
    
//     // init closest shop in subtree
//     closest[nd] = shop[nd] ? 0 : INF;   
//     for (auto i : adj[nd])
//         if (i.first != par)
//             closest[nd] = min(closest[nd], i.second + closest[i.first]);

//     return;
// }

// void dfs_bld(int nd) {
//     if (closest[nd] == INF) bld[nd][0] = INF;
//     else bld[nd][0] = -dist[nd] + closest[nd];
//     for (int i = 1; i < 20; i++) bld[nd][i] = min(bld[nd][i-1], bld[bl[nd][i-1]][i-1]);

//     for (auto i : adj[nd])
//         if (i.first != bl[nd][0])
//             dfs_bld(i.first);
// }

// inline int jmp(int nd, int k) {
//     for (int i = 19; i >= 0; i--) if ((k >> i) & 1) nd = bl[nd][i];
//     return nd;
// }

// inline bool on_path(int nd, int nd2) {
//     // checking if nd2 is on nd's path to root
//     return (dpth[nd] >= dpth[nd2] && jmp(nd, dpth[nd] - dpth[nd2]) == nd2);
// }

// void solve() {
//     cin >> n >> s >> q >> e; e--;
//     for (int i = 0; i < n-1; i++) {
//         int c; cin >> edges[i].first >> edges[i].second >> c;
//         edges[i].first--, edges[i].second--;
//         adj[edges[i].first].push_back({edges[i].second, c});
//         adj[edges[i].second].push_back({edges[i].first, c});
//     }

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

//     dfs(e, e, 0, 0);
//     dfs_bld(e);

//     for (int i = 0; i < q; i++) {
//         // a is a removed, b is b to find
//         int a, b; cin >> a >> b; a--, b--;

//         if (dpth[edges[a].first] < dpth[edges[a].second]) 
//             swap(edges[a].first, edges[a].second);

//         // check if escape possible
//         if (!on_path(b, edges[a].first)) {
//             cout << "escaped" << endl;
//             continue;
//         }

//         // not possible, so search
//         int val = INF;
//         int B = b;
//         for (int i = 19; i >= 0; i--) 
//             if (((dpth[edges[a].first] - dpth[b] + 1) >> i) & 1)
//                 val = min(val, bld[b][i]), 
//                 b = bl[b][i];

//         if (val == INF) {
//             cout << "oo" << endl;
//             continue;
//         }

//         cout << val + dist[B] << endl;
//         continue;
//     }

// }

// signed main() {
//     cin.tie(nullptr) -> ios::sync_with_stdio(false);
//     // freopen("main.in", "r", stdin);
//     int t; 
//     // cin >> t;
//     t=1;
//     while(t--) solve();
//     return 0;
// }

#include <bits/stdc++.h>
using namespace std;

#define int long long

const int maxn = 100000;
const int INF = 1e18;

int n, s, q, e;

vector<pair<int,int>> adj[maxn];
pair<int,int> edges[maxn];

int dist[maxn];
int dpth[maxn];
int closest[maxn];

int bl[maxn][20];
int bld[maxn][20];

int st[maxn], en[maxn], cur = 0;

void dfs(int nd, int par, int d) {
    st[nd] = cur++;
    dist[nd] = dist[par] + d;
    dpth[nd] = dpth[par] + 1;
    closest[nd] = (closest[nd] ? 0 : INF);

    for (auto i : adj[nd])
        if (i.first != par)
            dfs(i.first, nd, i.second);

    for (auto i : adj[nd])
        if (i.first != par && closest[i.first] != INF)
            closest[nd] = min(closest[nd], i.second + closest[i.first]);
    
    en[nd] = cur++;
}

void dfs_bl(int nd, int par) {
    bl[nd][0] = par;
    bld[nd][0] = (closest[nd] == INF ? INF : closest[nd] - dist[nd]);

    for (int i = 1; i < 20; i++) bl[nd][i] = bl[bl[nd][i-1]][i-1];
    for (int i = 1; i < 20; i++) bld[nd][i] = min(bld[nd][i-1], bld[bl[nd][i-1]][i-1]);

    for (auto i : adj[nd])
        if (i.first != par)
            dfs_bl(i.first, nd);
}

signed main() {
    freopen("main.in", "r", stdin);

    cin >> n >> s >> q >> e; e--;

    for (int i = 0; i < n-1; i++) {
        int a, b, c; cin >> a >> b >> c; a--, b--;
        adj[a].push_back({b, c});
        adj[b].push_back({a, c});
        edges[i] = make_pair(b, c);
    }

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

    dfs(e, e, 0);
    dfs_bl(e, e);

    for (int i = 0; i < q; i++) {
        int a, b; cin >> a >> b; a--, b--;
        if (dpth[edges[a].first] < dpth[edges[a].second]) swap(edges[a].first, edges[a].second);

        // can escape?
        if (!(st[edges[a].first] <= st[b] && en[b] <= en[edges[a].first])) {
            cout << "escaped" << endl;
            continue;
        }

        int cost = INF;
        int nd = b;
        for (int i = 19; i >= 0; i--)
            if (((dpth[b] - dpth[edges[a].first] + 1) >> i) & 1)
                cost = min(cost, bld[nd][i]), 
                nd = bl[nd][i];
        
        if (cost == INF) { cout << "oo" << endl; continue; }

        cout << cost + dist[b] << endl;
        continue;
    }

    return 0;
}

Compilation message (stderr)

valley.cpp: In function 'int main()':
valley.cpp:176:12: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  176 |     freopen("main.in", "r", stdin);
      |     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...