Cod sursa(job #3225061)

Utilizator RobertAcAcatrinei Robert-Marian RobertAc Data 16 aprilie 2024 20:41:33
Problema Obiective Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 5.18 kb
#include <bits/stdc++.h>
#ifdef LOCAL
#define in cin
#define out cout
#endif

using namespace std;

#ifndef LOCAL
ifstream in("obiective.in");
ofstream out("obiective.out");
#endif

const int nmax = 32005;
const int lgmax = 17;
int col = 1;
int color[nmax];

struct ctc
{
    vector<int> adj[nmax];
    int ind = 1;
    int depth[nmax], low[nmax];
    int state[nmax];
    stack<int> s;
    void adde(int a, int b)
    {
        adj[a].push_back(b);
    }
    void dfs(int nod = 1)
    {
        depth[nod] = low[nod] = ind++;
        s.push(nod);
        state[nod] = 1;
        for (auto i : adj[nod])
        {
            if (state[i] == 1)
            {
                low[nod] = min(low[nod], depth[i]);
            }
            else if (state[i] == 0)
            {
                dfs(i);
                low[nod] = min(low[nod], low[i]);
            }
        }
        if (low[nod] == depth[nod])
        {
            while (s.top() != nod)
            {
                color[s.top()] = col;
                state[s.top()] = 2;
                s.pop();
            }
            color[s.top()] = col;
            state[s.top()] = 2;
            s.pop();
            col++;
        }
    }
} root1;

struct sorttop
{
    vector<int> adj[nmax];
    int enters[nmax];
    vector<int> topp;
    bool viz[nmax];
    sorttop()
    {
        memset(viz, 0, sizeof viz);
        memset(enters, 0, sizeof enters);
    }
    void adde(int a, int b)
    {
        adj[a].push_back(b);
        enters[b]++;
    }
    void dfs(int nod)
    {
        viz[nod] = 1;
        topp.push_back(nod);
        for (auto i : adj[nod])
        {
            enters[i]--;
            if (enters[i] == 0)
            {
                dfs(i);
            }
        }
    }
    void dosort()
    {
        for (int i = 1; i <= col; i++)
        {
            if (!viz[i] && enters[i] == 0)
            {
                dfs(i);
            }
        }
    }
} root2;

vector<int> revadj[nmax];
vector<int> adj[nmax];
int depth[nmax];
bool viz[nmax];
int root;
int dp[nmax][lgmax];

struct LCA
{
    int parent[nmax][lgmax];
    void dfs(int nod, int p)
    {
        parent[nod][0] = p;
        for (auto i = 1; i < lgmax; i++)
        {
            parent[nod][i] = parent[parent[nod][i - 1]][i - 1];
        }
        for (auto i : adj[nod])
        {
            dfs(i, nod);
        }
    }
    int lca(int a, int b)
    {
        if (depth[a] < depth[b])
        {
            swap(a, b);
        }
        for (int i = lgmax - 1; i >= 0; i--)
        {
            if (depth[parent[a][i]] >= depth[b])
            {
                a = parent[a][i];
            }
        }
        if (a == b)
        {
            return a;
        }
        for (int i = lgmax - 1; i >= 0; i--)
        {
            if (parent[a][i] != parent[b][i])
            {
                a = parent[a][i];
                b = parent[b][i];
            }
        }
        return parent[a][0];
    }
} root3;

int bestnode(int a, int b)
{
    if (depth[a] < depth[b])
    {
        return a;
    }
    return b;
}

void dfs(int nod, int lg)
{
    dp[nod][lg] = nod;
    for (auto i : adj[nod])
    {
        dfs(i, lg);
        dp[nod][lg] = bestnode(dp[nod][lg], dp[i][lg]);
    }
    if (lg == 0)
    {
        for (auto i : revadj[nod])
        {
            dp[nod][0] = bestnode(dp[nod][0], i);
        }
    }
    else
    {
        dp[nod][lg] = bestnode(dp[nod][lg], dp[dp[nod][lg - 1]][lg - 1]);
    }
}

int bins(int nod, int d)
{
    int ans = 0;
    if (depth[nod] == d)
        ans = -1;
    for (int step = lgmax - 1; step >= 0; step--)
    {
        if (depth[dp[nod][step]] > d)
        {
            nod = dp[nod][step];
            ans += (1 << step);
        }
    }
    return ans + 1;
}

int main()
{
    int n, m;
    in >> n >> m;
    vector<pair<int, int>> muchii;
    for (int i = 0; i < m; i++)
    {
        int a, b;
        in >> a >> b;
        muchii.push_back({a, b});
        root1.adde(a, b);
    }
    for (int i = 1; i <= n; i++)
    {
        if (root1.state[i] == 0)
        {

            root1.dfs(i);
        }
    }
    col--;
    for (auto i : muchii)
    {
        if (color[i.first] != color[i.second])
        {
            assert(color[i.first] != 0);
            assert(color[i.second] != 0);
            root2.adde(color[i.first], color[i.second]);
            revadj[color[i.second]].push_back(color[i.first]);
        }
    }
    root2.dosort();
    auto topp = root2.topp;
    root = topp[0];
    depth[root] = 1;
    viz[root] = 1;
    for (int i = 1; i < col; i++)
    {
        int maxx = 0;
        int maxxind = 0;
        for (auto j : revadj[topp[i]])
        {
            if (viz[j])
            {
                if (maxx < depth[j])
                {
                    maxx = depth[j];
                    maxxind = j;
                }
            }
        }
        viz[topp[i]] = 1;
        depth[topp[i]] = maxx + 1;
        adj[maxxind].push_back(topp[i]);
    }
    root3.dfs(root, 0);
    for (int i = 0; i < lgmax; i++)
    {
        dfs(root, i);
    }
    int q;
    in >> q;
    for (int i = 0; i < q; i++)
    {
        int a, b;
        in >> a >> b;
        int c = root3.lca(color[a], color[b]);
        out << bins(color[a], depth[c]) << '\n';
    }
}