Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- const int MAX = 2e5+5;
- int is_cycle[MAX], cycle[MAX], line[MAX];
- int count_cycle, count_line, pos_cycle[MAX], sz_cycle[MAX];
- int color[MAX], up[MAX][32];
- vector<int> order;
- int n, q;
- void dfs(int u) {
- order.push_back(u);
- color[u] = 1;
- if (color[up[u][0]] == 1) {
- int to = order.size();
- int cnt = 0;
- do {
- ++cnt;
- --to;
- is_cycle[order[to]] = true;
- cycle[order[to]] = count_cycle;
- } while (to >= 0 and order[to] != up[u][0]);
- to = order.size()-cnt;
- for (int i = to; i < (int)order.size(); ++i) {
- pos_cycle[order[i]] = i-to;
- }
- sz_cycle[count_cycle] = cnt;
- ++count_cycle;
- } else if (color[up[u][0]] == 0) {
- dfs(up[u][0]);
- }
- if (!is_cycle[u]) {
- if (is_cycle[up[u][0]] == 1) {
- line[u] = count_line++;
- } else {
- line[u] = line[up[u][0]];
- }
- }
- color[u] = 2;
- order.pop_back();
- }
- void same_cycle(int a, int b, int dd=0) {
- if (cycle[a] != cycle[b]) {
- cout << "-1\n";
- } else {
- cout << dd+(pos_cycle[b] - pos_cycle[a] + sz_cycle[cycle[a]]) % sz_cycle[cycle[a]] << '\n';
- }
- }
- int dist(int node) {
- int dd = 0;
- for (int k = 30; k >= 0; --k) {
- if (!is_cycle[up[node][k]]) {
- node = up[node][k];
- dd += (1 << k);
- }
- }
- node = up[node][0];
- return dd + 1;
- }
- int main() {
- ios_base::sync_with_stdio(0), cin.tie(0);
- cin >> n >> q;
- memset(up, -1, sizeof up);
- memset(line, -1, sizeof line);
- memset(cycle, -1, sizeof cycle);
- memset(pos_cycle, -1, sizeof pos_cycle);
- for (int i = 0, a; i < n; ++i) {
- cin >> a, --a;
- up[i][0] = a;
- }
- for (int k = 1; k < 31; ++k) {
- for (int i = 0; i < n; ++i) {
- if (~up[i][k-1]) up[i][k] = up[up[i][k-1]][k-1];
- }
- }
- for (int i = 0; i < n; ++i) {
- if (color[i] == 0) {
- dfs(i);
- }
- }
- int a, b;
- while (q--) {
- cin >> a >> b, --a, --b;
- if (is_cycle[a] and is_cycle[b]) {
- same_cycle(a, b);
- } else if (is_cycle[a]) {
- cout << "-1\n";
- } else if (is_cycle[b]) {
- int ans = 0;
- for (int k = 30; k >= 0; --k) {
- if (!is_cycle[up[a][k]]) {
- a = up[a][k];
- ans += (1 << k);
- }
- }
- a = up[a][0];
- same_cycle(a, b, ans+1);
- } else {
- if (line[a] != line[b]) {
- cout << "-1\n";
- } else {
- int da = dist(a);
- int db = dist(b);
- if (db >= da) {
- if (a != b) {
- cout << "-1\n";
- } else {
- cout << "0\n";
- }
- } else {
- int diff = da-db;
- int ans = 0;
- for (int k = 30; k >= 0; --k) {
- if (diff >= (1 << k)) {
- a = up[a][k];
- diff -= (1 << k);
- ans += (1 << k);
- }
- }
- if (a != b) {
- cout << "-1\n";
- } else {
- cout << ans << '\n';
- }
- }
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment