Hey guys...
So I was solving this problem from CSES.
Here is what I have tried...
My idea
Firsly ,
- I am finding all cycles in graph
- For all nodes , keeping track of in which cycle it belongs to and what is the node no. in that cycle for that node.
- erasing all cycle causing edges
- then applying binary lifting on inverted tree.
now ready to answer queries.
if given starting node is involved any cycle then ending node should also be in same cycle. otherwise ans is -1.
If both are in same cycle then we can compute distance between them in O(1) using node nos. of both node.
Now , if Starting node is not in any cycle.
Then ending node must be ancestor of it otherwise ans is -1 (not reachable) Now as ending node is ancestor of starting node , we can walk upto that node and compute desired no. of jumps. It will be in O(logn).
By implementing this idea , I am getting WA in one TC ( Out of 11 ).
You can find my code here.
code
#include<bits/stdc++.h>
#define maxn 300005
#define ll long long int
using namespace std;
// https://cses.fi/problemset/task/1160/
set<int> par[maxn];
vector<int> nxt(maxn);
vector<int> kai_cyc(maxn,-1),kyo_node(maxn,-1);
vector<bool> v1(maxn,false),v2(maxn,false);
vector<vector<int>> cycle;
vector<int> tmp;
int cyc_id=0;
int nn=0;
int start=-1;
vector<int> tin(maxn),tout(maxn);
int tem=0;
vector<int> latkav;
void dfs(int n)
{
v1[n]=true;
int c=nxt[n];
if(v1[c] && !v2[c])
{
nxt[n]=-1;
par[c].erase(n);
latkav.push_back(n);
start=c;
}
if(!v1[c]) dfs(c);
if(start!=-1)
{
tmp.push_back(n);
kai_cyc[n]=cyc_id;
kyo_node[n]=nn++;
if(n==start)
{
cycle.push_back(tmp);
start=-1;
tmp.clear();
nn=0;
cyc_id++;
}
}
v2[n]=true;
}
vector<vector<int>> up;
int mxh;
void dfs1(int n,int p)
{
tin[n]=tem++;
up[n][0]=p;
for(int i=1;i<=mxh;i++)
{
if(up[n][i-1]!=-1) { up[n][i]=up[up[n][i-1]][i-1]; }
}
for(int c:par[n]) dfs1(c,n);
tout[n]=tem++;
}
bool isanc(int u,int v)
{
return (tin[u]<=tin[v] && tout[u]>=tout[v]);
}
int main()
{
jaldi
int n,q;
cin>>n>>q;
for(int i=1,x;i<=n;i++)
{
cin>>x;
nxt[i]=x;
par[x].insert(i);
}
for(int i=1;i<=n;i++)
{
if(!v1[i]) dfs(i);
}
//for(vector<int> v:cycle) { deb(v); } //if in same cycle then o(1) ans, else binary lifting
mxh=ceil(log2(n));
up.assign(n+1,vector<int>(mxh+1,-1));
for(int x:latkav) dfs1(x,-1);
while(q--)
{
int start,end;
cin>>start>>end;
if(start==end) { cout<<"0\n"; continue; }
if(kai_cyc[start]!=-1)
{
if(kai_cyc[start]==kai_cyc[end])
{
int s=kyo_node[start];
int e=kyo_node[end];
int sz=cycle[kai_cyc[start]].size();
cout<<(s-e+sz)%sz<<"\n";
}
else { cout<<"-1\n"; }
continue;
}
if(isanc(end,start))
{
int jump=0;
for(int i=mxh;i>=0;i--)
{
if(up[start][i]!=-1 && !isanc(up[start][i],end)) { start=up[start][i]; jump+=1<<i; }
}
cout<<jump+1<<"\n";
}
else { cout<<"-1\n"; }
}
return 0;
}
So , can someone point out what am I doing wrong or any cases that I am missing.
Thanks in advance :)