Cod sursa(job #1474297)

Utilizator tudi98Cozma Tudor tudi98 Data 21 august 2015 18:46:49
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.4 kb
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
 
const int Nmax = 32000;
 
int N,M,T,SCC = 0,root;
vector<int> Adj[Nmax+1],TAdj[Nmax+1];
bool seen[Nmax+1],come[Nmax+1];
stack<int> KosarajuST;
int comp[Nmax+1];
set<int> G[Nmax+1];
int ST[Nmax+1],K[Nmax+1];
vector<int> Graph[Nmax+1];
int Ancestor[17][Nmax+1],Up[17][Nmax+1],lvl[Nmax+1];
 
struct Compare
{
    inline bool operator()(const int& Rs,const int& Ls)
    {
        return K[Rs] < K[Ls];
    }
};
 
void Dfs1(int node)
{
    seen[node] = 1;
    for (vector<int>::iterator it = Adj[node].begin(); it != Adj[node].end(); ++it)
        if (!seen[*it])
            Dfs1(*it);
    KosarajuST.push(node);
}
 
void Dfs2(int node)
{
    comp[node] = SCC;
    for (vector<int>::iterator it = TAdj[node].begin(); it != TAdj[node].end(); ++it)
        if (!comp[*it])
            Dfs2(*it);
}
 
void Kosaraju()
{
    for (int i = 1; i <= N; ++i)
        if (!seen[i])
            Dfs1(i);
 
    while (!KosarajuST.empty())
    {
        if (!comp[KosarajuST.top()])
        {
            ++SCC;   
            Dfs2(KosarajuST.top());
        }
        KosarajuST.pop();
    }   
}
 
void BuildDAG()
{
    for (int i = 1; i <= N; ++i)
        for (vector<int>::iterator it = Adj[i].begin(); it != Adj[i].end(); ++it)
            if(comp[i] != comp[*it]) 
                G[comp[i]].insert(comp[*it]);
}
 
void Tsort(int node)
{
    seen[node] = 1;
    for (set<int>::iterator it = G[node].begin(); it != G[node].end(); ++it)
        if (!seen[*it])
            Tsort(*it);
    ST[++ST[0]] = node;
}
 
void TopologicalSort()
{
    memset(seen, 0, sizeof seen);
    for (int i = 1; i <= SCC; ++i)
        if (!seen[i])
            Tsort(i);   
 
    root = ST[ST[0]];
 
    for (int i = 1; i <= ST[ST[0]]; ++i)
        K[ST[i]] = ST[0] - i + 1;
 
    for (int i = 1; i <= SCC; ++i)
    {
        Graph[i] = vector<int>(G[i].begin(),G[i].end());
        sort(Graph[i].begin(),Graph[i].end(),Compare());
    }
}
       
void BuildTree(int node)
{
    for (vector<int>::iterator it = Graph[node].begin(); it != Graph[node].end(); ++it)
    {
        if (!Ancestor[0][*it])
        {
            Ancestor[0][*it] = node;
            lvl[*it] = lvl[node] + 1;
            BuildTree(*it);
        }
 
        if (!Up[0][*it] || lvl[Up[0][*it]] > lvl[node])
            Up[0][*it] = node;
 
        if(node == root) return;
 
        if (!Up[0][node] || lvl[Up[0][node]] > lvl[Up[0][*it]])
            Up[0][node] = Up[0][*it];
    }   
}
         
void BuildLCA()
{
    for (int i = 1; (1 << i) <= SCC; ++i)
        for (int j = 1; j <= SCC; ++j)
        {
            Ancestor[i][j] = Ancestor[i-1][Ancestor[i-1][j]];
            Up[i][j] = Up[i-1][Up[i-1][j]]; 
        }
}
 
int lca(int x,int y)
{
    if(lvl[x] < lvl[y])
        swap(x,y);
     
    int logx,logy;
    for (logx = 1; 1 << logx < lvl[x]; ++logx);
    for (logx = 1; 1 << logy < lvl[y]; ++logy);
 
    for (;lvl[x] != lvl[y]; --logx)
        if (lvl[x] - (1 << logx) >= lvl[y])
            x = Ancestor[logx][x];
 
    if (x == y) return x;
 
    for (; logy >= 0; --logy)
        if (Ancestor[logy][y] != Ancestor[logy][x])
        {
            y = Ancestor[logy][y];
            x = Ancestor[logy][x];
        }
 
    return Ancestor[0][x];
}
 
int Solve(int from,int to)
{
    if (lvl[from] <= lvl[to]) return 0;
 
    int log;
    for (log = 1; (1 << log) <= lvl[from]; ++log);
    --log;
 
    int Ret = 0;
    for (; log >= 0; --log)
        if (Up[log][from] && lvl[Up[log][from]] > lvl[to])
        {
            from = Up[log][from];
            Ret += 1 << log;
        }
 
    return Ret + 1;
}
 
int main()
{
    freopen("obiective.in", "r", stdin);
    freopen("obiective.out", "w", stdout);
 
    scanf("%d%d", &N, &M);
    for (int i = 1; i <= M; ++i)
    {
        int a,b;
        scanf("%d%d", &a, &b);
        Adj[a].push_back(b);
        TAdj[b].push_back(a);
    }
 
    Kosaraju();
    BuildDAG();
    TopologicalSort();
    BuildTree(root);
    BuildLCA();  
         
    scanf("%d",&T);
    for (int i = 1; i <= T; ++i)
    {
        int a,b;
        scanf("%d%d", &a, &b);
        a = comp[a];
        b = comp[b];
        int l = lca(a,b);   
        printf("%d\n", Solve(a,l)); 
    }
}