Planets Queries II CSES
Difference between en3 and en4, changed 3,374 character(s)
Hey guys... ↵

Recently I was solving this [problem](https://cses.fi/problemset/task/1160/) from CSES.↵

Here is what I have tried...↵

<spoiler summary="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 (talking in inverted tree) , we can walk upto that node ↵
        and compute desired no. of jumps.↵
     ↵
         It will be in O(logn).↵


</spoiler>↵



By implementing this idea , I am getting WA in one TC ( Out of 11 ). ↵

You can find my code here.↵

<spoiler summary="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;↵
}↵
~~~~~↵
</spoiler>↵

So , can someone point out what am I doing wrong or any cases that I am missing.↵

Thanks in advance :)↵

----------------------------------------------------------------------------------↵

**UPD**↵

As [user:pwild,2020-06-25] sir pointed out , I was missing that cases.↵

To overcome that , I just added small logic to my code and it got ACCEPTED.↵

If you want to see code...↵


<spoiler summary="accepted code">↵


~~~~~↵
#include<bits/stdc++.h>↵

#define maxn 200005↵
#define ll long long int↵
#define fastio ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);↵

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])↵
    {↵
        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()↵
{↵
    fastio↵

    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);↵
    }↵

    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↵
        {↵
            int jump=0;↵
            for(int i=mxh;i>=0;i--)↵
            {↵
                if(up[start][i]!=-1) { start=up[start][i]; jump+=1<<i;}↵
            }↵
            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+jump)<<"\n"; ↵
            }↵
            else { cout<<"-1\n"; }↵
        }↵
    }↵
    return 0;↵
}↵

~~~~~↵

</spoiler>↵


 ↵

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en4 English Peace_789 2020-06-25 06:58:52 3374 Tiny change: 'nt to see accepted code...\n\n<spoil' -> 'nt to see code...\n\n\n<spoil'
en3 English Peace_789 2020-06-24 21:12:09 49
en2 English Peace_789 2020-06-24 21:07:59 11 Tiny change: 'ys... \n\nSo I was sol' -> 'ys... \n\nRecently I was sol'
en1 English Peace_789 2020-06-24 21:07:32 3910 Initial revision (published)