Table of Contents

ExplanationImplementation

Explanation

Let's solve the q=1q = 1 subtask first. Let's reverse the graph so that in this query, we are solving for the longest path from tt to an unblocked node. Here, we can just use DP to compute the longest path to every possible node ss. If dpi\texttt{dp}_i stores the longest path from tt to ii, then dpv=max(dpv,dpu+1)\texttt{dp}_v = \max(\texttt{dp}_v, \texttt{dp}_u + 1), over all vv where uu and vv are connected by an edge and is reachable from tt in the reverse graph. Since it is guaranteed v<uv < u, this can be done with a single sweep.

Now, let's bring in sqrt decomposition. The variable in question is the number of blocked nodes, denoted as yy. Let's denote B=105B = \sqrt{10^5} and suppose all queries have yBy \geq B. Since the sum of yy over all queries is bounded by 10510^5, there can be no more than 105B=B\frac{10^5}{B} = B queries. The number of queries is small enough that we can run an O(n)\mathcal{O}(n) DP algorithm each time, leading to a O(Bn)\mathcal{O}({Bn}) runtime.

To handle queries with y<By < B, we have to do some preprocessing. For each node, we can store the BB longest paths that ends at that node, each originating from a different initial node. This needs to be done with careful pruning of paths with different lengths originating from the same node. This precomputation is approximately O(Bm+nlog(Bn))\mathcal{O}(Bm + n \log(Bn)), since we need to sort the longest paths after we process each node. To answer queries, we can just loop through the BB longest paths of tt, and find the longest one starting at an unblocked node. This will also take O(Bn)\mathcal{O}({Bn}) time.

Warning: Choosing B

We do not want to choose BB such that it equals 105\sqrt{10^5} exactly! It is apparent that the latter case is much more memory and runtime heavy than the former case, so we need to weigh down BB to minimize the effects of the second case. In my code, I use B=100B = 100.

Implementation

Time Complexity: O(Bm+nlog(Bn)+Bn)\mathcal{O}(Bm + n \log(Bn) + Bn)

C++

#include <bits/stdc++.h>
using namespace std;
const int SQ = 100; // cutoff for sqrt decomp
int main() {
cin.tie(0)->sync_with_stdio(0);
int n, m, q;
cin >> n >> m >> q;
vector<vector<int>> rg(n);
for (int i = 0; i < m; i++) {

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!