Pagini recente » Cod sursa (job #1528817) | Cod sursa (job #1995096) | Cod sursa (job #2573183) | Cod sursa (job #2529992) | Cod sursa (job #2664726)
#include <bits/stdc++.h>
using namespace std;
ifstream fin("obiective.in");
ofstream fout("obiective.out");
vector < vector <int> > g, tg, SCCs, sparseTable, anc;
vector < set <int> > mg; // meta graph
vector <int> topoSort, SCC, depth, fp;
vector <bool> seen;
int V, E;
int numSCC;
int eulerOrd;
void readGraph(){
fin >> V >> E;
g.resize(V + 1);
tg.resize(V + 1);
topoSort.reserve(V);
SCCs.reserve(V);
SCC.resize(V + 1);
seen.resize(V + 1);
for(int e = 0; e < E; ++e){
int from, to;
fin >> from >> to;
g[from].push_back(to);
tg[to].push_back(from);
}
}
void topologicalSort(int node){
seen[node] = true;
for(const int &adj : g[node])
if(!seen[adj])
topologicalSort(adj);
topoSort.push_back(node);
}
void DFS(int node, vector <int> &component){
seen[node] = false;
SCC[node] = numSCC;
component.push_back(node);
for(const int &adj : tg[node])
if(seen[adj])
DFS(adj, component);
}
void build_mg(){
mg.resize(numSCC + 1);
for(int scc = 0; scc < numSCC; ++scc)
for(int &node : SCCs[scc])
for(int &adj : g[node])
if(SCC[node] != SCC[adj])
mg[scc + 1].insert(SCC[adj] + 1);
V = numSCC;
depth.resize(V + 1);
sparseTable.resize((int)log2(2 * V + 2) + 1, vector <int>(2 * V + 2) );
fp.resize(V + 1);
anc.resize((int)log2(V + 1) + 1, vector <int>(V + 1));
depth[0] = INT_MAX;
}
int minDepth(int a, int b){
if(depth[a] < depth[b])
return a;
return b;
}
void eulerTrav(int node, int d){
seen[node] = true;
depth[node] = d;
sparseTable[0][++eulerOrd] = node;
fp[node] = eulerOrd;
for(const int &adj : mg[node])
if(!seen[adj]){ // tree edge
anc[0][adj] = minDepth(anc[0][adj], node);
eulerTrav(adj, d + 1);
sparseTable[0][++eulerOrd] = node;
anc[0][node] = minDepth(anc[0][node], anc[0][adj]);
}
else { // fwd edge
anc[0][adj] = min(anc[0][adj], node);
}
}
void createSparseTable(){
for(int r = 1; (1 << r) <= eulerOrd; ++r)
for(int c = 1; c <= eulerOrd - (1 << r) + 1; ++c)
sparseTable[r][c] = minDepth(sparseTable[r - 1][c], sparseTable[r - 1][c + (1 << (r - 1))]);
}
void createAnc(){
for(int step = 1; (1 << step) <= V; ++step)
for(int node = 1; node <= V; ++node)
anc[step][node] = anc[step - 1][anc[step - 1][node]];
}
int LCA(int x, int y){
if(fp[x] > fp[y])
swap(x, y);
int seqLen = fp[y] - fp[x] + 1;
int lvl = (int)(log2(seqLen));
return minDepth(sparseTable[lvl][fp[x]], sparseTable[lvl][fp[x] + seqLen - (1 << lvl)]);
}
int main(){
readGraph();
for(int node = 1; node <= V; ++node)
if(!seen[node])
topologicalSort(node);
for(int idx = V - 1; idx >= 0; --idx)
if(seen[topoSort[idx]]){
vector <int> component;
component.reserve(V);
DFS(topoSort[idx], component);
SCCs.push_back(component);
++numSCC;
}
build_mg();
eulerTrav(1, 1);
createSparseTable();
createAnc();
for(int r = 0;r < (int)anc.size(); ++r){
for(int c = 0; c < (int)anc[r].size(); ++c)
cout << anc[r][c] << ' ';
cout << '\n';
}
int maxStep = (int)log2(V);
int T;
fin >> T;
for(; T; --T){
int a, b;
fin >> a >> b;
a = SCC[a] + 1;
b = SCC[b] + 1;
int lca = LCA(a, b);
if(a == lca)
fout << 0 << '\n';
else{
int ans = 0;
for(int step = maxStep; step >= 0; --step)
if(depth[anc[step][a]] > depth[lca]){
ans += (1 << step);
a = anc[step][a];
}
fout << ans + 1 << '\n';
}
}
}