Submission #1239204

#TimeUsernameProblemLanguageResultExecution timeMemory
1239204pvb.tunglamBitaro’s Party (JOI18_bitaro)C++20
100 / 100
1602 ms268248 KiB
#include <bits/stdc++.h>
#define hash  _hash_
#define y1    _y1_
#define left  _left_
#define right _right_
#define dec   _dec_

using namespace std;
using ll = long long;
using pii = pair<int,int>;

/*----------- I alone decide my fate! ------------*/
/*  I just do what I gotta, in the heat of the summer...  */

const int MAXN = 100000 + 5;
const int B    = 320;                        // ⌈√100000⌉

int N, M, Q;
vector<int> adj[MAXN], radj[MAXN];

/* √-decomposition: lưu B ứng viên dài nhất cho mỗi đỉnh */
vector<pii> best[MAXN];                      // (len, start), giảm dần len

/* cờ đỉnh “bận” – chỉ dùng để loại ở bước lấy đáp án */
bool ban[MAXN];

/* ===== Mảng phụ trợ cho merge nhanh ===== */
int seen[MAXN], tick_seen = 0;
inline void merge_into(vector<pii>& dst,
                       const vector<pii>& src) {
    static pii buf[2 * B + 5];
    int i = 0, j = 0, p = 0, na = dst.size(), nb = src.size();
    ++tick_seen;
    while ((i < na || j < nb) && p < B) {
        pii cand;
        if (j == nb || (i < na && dst[i].first >= src[j].first + 1))
            cand = dst[i++];                         // giữ nguyên độ dài
        else {
            cand = {src[j].first + 1, src[j].second}; // +1 khi qua cạnh
            ++j;
        }
        if (seen[cand.second] != tick_seen) {
            seen[cand.second] = tick_seen;
            buf[p++] = cand;
        }
    }
    dst.assign(buf, buf + p);
}

/* ===== Phần cho truy vấn “nặng” ===== */
bool vis[MAXN];          // tập reach
int  distv[MAXN];        // độ dài tốt nhất đến T  (–1 = chưa tới)

/*------------------------------------------------------------*/
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    /* ---- Nhập ---- */
    cin >> N >> M >> Q;
    for (int i = 0, u, v; i < M; ++i) {
        cin >> u >> v;
        adj[u].push_back(v);
        radj[v].push_back(u);
    }

    /* ---- Khởi tạo best ---- */
    for (int u = 1; u <= N; ++u) best[u].push_back({0, u});

    /* ---- Tiền xử lý cho truy vấn nhẹ ---- */
    for (int u = 1; u <= N; ++u)
        for (int v : adj[u])
            merge_into(best[v], best[u]);

    vector<int> busy, reach;
    queue<int> que;

    /* ======================================================== */
    while (Q--) {
        int T, Y;  cin >> T >> Y;
        busy.clear();
        for (int i = 0, x; i < Y; ++i) {
            cin >> x;
            ban[x] = true;
            busy.push_back(x);
        }

        int ans = -1;

        /* ---------- Truy vấn “nhẹ” ---------- */
        if (Y < B) {
            for (const auto& p : best[T])
                if (!ban[p.second]) { ans = p.first; break; }
        }
        /* ---------- Truy vấn “nặng” ---------- */
        else {
            /* 1. BFS ngược lấy tập reach */
            reach.clear();
            que.push(T); vis[T] = true;
            while (!que.empty()) {
                int v = que.front(); que.pop();
                reach.push_back(v);
                for (int u : radj[v])
                    if (!vis[u]) { vis[u] = true; que.push(u); }
            }

            /* 2. DP topo ngược: len dài nhất tới T */
            sort(reach.begin(), reach.end(), greater<int>());
            for (int u : reach) distv[u] = -1;   // -1 = chưa tới
            distv[T] = 0;                        // gốc

            for (int u : reach) {
                if (u != T) {
                    int best_len = -1;
                    for (int v : adj[u])
                        if (vis[v] && distv[v] != -1)
                            best_len = max(best_len, distv[v] + 1);
                    distv[u] = best_len;
                }
                if (distv[u] != -1 && !ban[u])
                    ans = max(ans, distv[u]);
            }

            /* 3. Reset cờ vis cho lần sau */
            for (int u : reach) vis[u] = false;
        }

        cout << ans << '\n';

        /* ---- Gỡ cờ bận ---- */
        for (int x : busy) ban[x] = false;
    }
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...