This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
/**
* author: derrick20
* created: 1/25/22 9:47 PM
*/
import java.io.*;
import java.util.*;
import static java.lang.Math.*;
public class bitaro {
static FastScanner sc = new FastScanner();
static PrintWriter out = new PrintWriter(System.out);
public static void main(String[] args) {
int N = sc.nextInt(), M = sc.nextInt(), Q = sc.nextInt();
adjList = new ArrayDeque[N];
Arrays.setAll(adjList, i -> new ArrayDeque<>());
for (int i = 0; i < M; i++) {
int u = sc.nextInt() - 1;
int v = sc.nextInt() - 1;
adjList[v].add(u);
}
sqrtN = N + 1; // (int) sqrt(N) / 3;
dpPaths = new int[N][sqrtN][2];
vis = new boolean[N];
seen = new boolean[N];
seenSet = new int[N];
maxPath = new int[N];
for (int u = 0; u < N; u++) {
if (!vis[u]) {
vis[u] = true;
solve(u);
}
}
boolean[] busy = new boolean[N];
while (Q-->0) {
int partyHost = sc.nextInt() - 1;
int busyCount = sc.nextInt();
int[] busyBeavers = new int[busyCount];
Arrays.setAll(busyBeavers, i -> sc.nextInt() - 1);
for (int beaver : busyBeavers) {
busy[beaver] = true;
}
int ans = -1;
if (busyCount < sqrtN) {
for (int i = sqrtN - 1; i >= 0; i--) {
if (dpPaths[partyHost][i][0] == 0) break;
if (!busy[dpPaths[partyHost][i][1]]) {
ans = dpPaths[partyHost][i][0];
break;
}
}
if (ans == -1 && !busy[partyHost]) {
ans = 0;
}
} else {
dpLarge = new int[N];
Arrays.fill(dpLarge, -1);
solveLarge(partyHost, busy);
ans = dpLarge[partyHost];
}
out.println(ans);
for (int beaver : busyBeavers) {
busy[beaver] = false;
}
}
out.close();
}
static ArrayDeque<Integer>[] adjList;
static int sqrtN;
static int[][][] dpPaths;
static boolean[] vis;
static int[] dpLarge;
static void solveLarge(int node, boolean[] busy) {
if (!busy[node]) {
dpLarge[node] = 0;
}
for (int adj : adjList[node]) {
solveLarge(adj, busy);
if (dpLarge[adj] != -1)
dpLarge[node] = max(dpLarge[node], 1 + dpLarge[adj]);
}
}
static boolean[] seen;
static int[] seenSet;
static int[] maxPath;
static void solve(int node) {
int deg = adjList[node].size();
if (deg == 0) return;
HashMap<Integer, Integer> paths = new HashMap<>();
int seenSize = 0;
for (int adj : adjList[node]) {
if (!vis[adj]) {
vis[adj] = true;
solve(adj);
}
if (!seen[adj]) {
seen[adj] = true;
seenSet[seenSize++] = adj;
}
maxPath[adj] = max(1, maxPath[adj]);
// paths.merge(adj, 1, Integer::max);
for (int i = sqrtN - 1; i >= 0; i--) {
int dist = dpPaths[adj][i][0];
int dest = dpPaths[adj][i][1];
if (dist == 0) break;
if (!seen[dest]) {
seen[dest] = true;
seenSet[seenSize++] = dest;
}
maxPath[dest] = max(dist + 1, maxPath[dest]);
// paths.merge(dpPaths[adj][i][1], dpPaths[adj][i][0] + 1, Integer::max);
}
}
int[][] collectedPaths = new int[deg * sqrtN + deg][2];
int ptr = 0;
for (int i = 0; i < seenSize; i++) {
int dest = seenSet[i];
collectedPaths[ptr++] = new int[]{maxPath[dest], dest};
seen[dest] = false;
maxPath[dest] = 0;
}
Arrays.sort(collectedPaths, Comparator.comparingInt(path -> path[0]));
System.arraycopy(collectedPaths, collectedPaths.length - sqrtN, dpPaths[node], 0, sqrtN);
}
static class FastScanner {
private int BS = 1 << 16;
private char NC = (char) 0;
private byte[] buf = new byte[BS];
private int bId = 0, size = 0;
private char c = NC;
private double cnt = 1;
private BufferedInputStream in;
public FastScanner() {
in = new BufferedInputStream(System.in, BS);
}
public FastScanner(String s) {
try {
in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
} catch (Exception e) {
in = new BufferedInputStream(System.in, BS);
}
}
char getChar() {
while (bId == size) {
try {
size = in.read(buf);
} catch (Exception e) {
return NC;
}
if (size == -1) return NC;
bId = 0;
}
return (char) buf[bId++];
}
int nextInt() {
return (int) nextLong();
}
long nextLong() {
cnt = 1;
boolean neg = false;
if (c == NC) c = getChar();
for (; (c < '0' || c > '9'); c = getChar()) {
if (c == '-') neg = true;
}
long res = 0;
for (; c >= '0' && c <= '9'; c = getChar()) {
res = (res << 3) + (res << 1) + c - '0';
cnt *= 10;
}
return neg ? -res : res;
}
double nextDouble() {
boolean neg = false;
if (c == NC) c = getChar();
for (; (c < '0' || c > '9'); c = getChar()) {
if (c == '-') neg = true;
}
double cur = nextLong();
if (c != '.') {
return neg ? -cur : cur;
} else {
double frac = nextLong() / cnt;
return neg ? -cur - frac : cur + frac;
}
}
String next() {
StringBuilder res = new StringBuilder();
while (c <= 32) c = getChar();
while (c > 32) {
res.append(c);
c = getChar();
}
return res.toString();
}
String nextLine() {
StringBuilder res = new StringBuilder();
while (c <= 32) c = getChar();
while (c != '\n') {
res.append(c);
c = getChar();
}
return res.toString();
}
boolean hasNext() {
if (c > 32) return true;
while (true) {
c = getChar();
if (c == NC) return false;
else if (c > 32) return true;
}
}
}
static void ASSERT(boolean assertion, String message) {
if (!assertion) throw new AssertionError(message);
}
static void ASSERT(boolean assertion) {
if (!assertion) throw new AssertionError();
}
}
Compilation message (stderr)
Note: bitaro.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |