#include <cstdio>
#include <vector>
using namespace std;
const int MAX = 100020, BIT_MAX = 17;
int n, to[MAX], numQuery, qType[MAX], qA[MAX], qB[MAX];
vector < int > children[MAX];
void input(){
scanf("%d", &n);
int i;
for(i = 1; i<=n; i++){
scanf("%d", &to[i]);
children[to[i]].push_back(i);
}
scanf("%d", &numQuery);
for(i = 0; i<numQuery; i++){
scanf("%d%d", &qType[i], &qA[i]);
if(qType[i] == 2) scanf("%d", &qB[i]);
}
}
int visited[MAX], cFull, cycleNum[MAX], cycleOrder[MAX], cycleSize[MAX];
int findCycle(int now, int visitNum){
visited[now] = visitNum;
if(visited[to[now]] == 0){
int t = findCycle(to[now], visitNum);
if(t){
cycleNum[now] = cFull;
cycleOrder[now] = cycleOrder[to[now]]+1;
} else {
cycleNum[now] = -abs(cycleNum[to[now]]);
cycleOrder[now] = cycleOrder[to[now]];
}
if(now == t) return 0;
else return t;
} else if(visited[to[now]] == visitNum){
cycleNum[now] = ++cFull;
cycleOrder[now] = 1;
return to[now];
} else {
cycleNum[now] = -abs(cycleNum[to[now]]);
cycleOrder[now] = cycleOrder[to[now]];
return 0;
}
}
int depth[MAX], p[20][MAX];
void calcDepth(int now){
int i;
for(i = 0; i<children[now].size(); i++){
int nextNum = children[now][i];
depth[nextNum] = depth[now]+1;
calcDepth(nextNum);
}
}
void init(){
int i, v = 1;
for(i = 1; i<=n; i++){
if(visited[i] == 0)
findCycle(i, v++);
}
for(i = 1; i<=n; i++){
if(cycleNum[i] < 0){
if(cycleNum[to[i]] == cycleNum[i]) p[0][i] = to[i];
else {
p[0][i] = i;
calcDepth(i);
}
} else {
cycleSize[cycleNum[i]]++;
p[0][i] = i;
}
}
int lvl = 1;
for(lvl = 1; lvl<=BIT_MAX; lvl++){
for(i = 1; i<=n; i++)
p[lvl][i] = p[lvl-1][p[lvl-1][i]];
}
}
int uf[MAX], firstCut[MAX];
bool cycleOK[MAX];
int getParent(int num){
if(uf[num] == num) return num;
return uf[num] = getParent(uf[num]);
}
void link(int a, int b){
if(getParent(a) == getParent(b)){
cycleOK[cycleNum[a]] = 1;
} else {
uf[getParent(a)] = getParent(b);
}
}
void cut(){
int i, tNext[MAX];
for(i = 1; i<=n; i++){
tNext[i] = to[i];
uf[i] = i;
}
for(i = 0; i<numQuery; i++){
if(qType[i] == 1){
if(cycleNum[qA[i]] > 0 && firstCut[cycleNum[qA[i]]] == 0)
firstCut[cycleNum[qA[i]]] = cycleOrder[qA[i]];
tNext[qA[i]] = 0;
}
}
for(i = 1; i<=n; i++){
if(tNext[i]){
link(i, tNext[i]);
}
}
}
int cycleDist(int f, int s){
int cn = cycleNum[f];
if(cycleOK[cn] ||
(cycleOrder[f] > cycleOrder[s]
? !(cycleOrder[f] >= firstCut[cn] && firstCut[cn] > cycleOrder[s])
: !(cycleOrder[f] >= firstCut[cn] || firstCut[cn] > cycleOrder[s]))){
int cs = cycleSize[cn];
return (cycleOrder[f]-cycleOrder[s]+cs) % cs;
} else return -1;
}
int res[MAX];
void solve(){
int i;
for(i = numQuery-1; i>=0; i--){
if(qType[i] == 1){
link(qA[i], to[qA[i]]);
} else {
res[i] = -1;
int f = qA[i], s = qB[i];
if(f == s) res[i] = 0;
else if(getParent(f) == getParent(s)){
if(cycleNum[s] > 0){
if(cycleNum[f] == cycleNum[s]){
//사이클 -> 사이클
res[i] = cycleDist(f, s);
} else if(cycleNum[f] == -cycleNum[s]){
//트리 -> 사이클
int t = cycleDist(to[p[BIT_MAX][f]], s);
if(t != -1)
res[i] = depth[f]+1 + t;
}
} else {
if(cycleNum[f] == cycleNum[s] && cycleOrder[f] == cycleOrder[s] && depth[s] < depth[f]){
//트리 -> 트리
int dist = depth[f]-depth[s];
int t;
for(t = 0; t<=BIT_MAX; t++){
if(dist & (1<<t)){
f = p[t][f];
}
}
if(f == s)
res[i] = dist;
}
}
}
}
}
for(i = 0; i<numQuery; i++){
if(qType[i] == 2){
printf("%d\n", res[i]);
}
}
}
int main(){
input();
init();
cut();
solve();
return 0;
}
Compilation message
specialg.cpp: In function 'int findCycle(int, int)':
specialg.cpp:38:42: error: 'abs' was not declared in this scope
specialg.cpp:49:41: error: 'abs' was not declared in this scope
specialg.cpp: In function 'void calcDepth(int)':
specialg.cpp:59:34: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
specialg.cpp: In function 'void input()':
specialg.cpp:11:17: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
specialg.cpp:15:22: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
specialg.cpp:19:24: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
specialg.cpp:21:35: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
specialg.cpp:22:40: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]