Pagini recente » Monitorul de evaluare | Cod sursa (job #2359087) | Cod sursa (job #1722335) | Cod sursa (job #2367173) | Cod sursa (job #3326566)
#include <bits/stdc++.h>
using namespace std;
const int NMAX = 35002;
ifstream fin("obiective.in");
ofstream fout("obiective.out");
int N, M, T;
vector<int> graph[NMAX], graph_tr[NMAX];
int viz[NMAX];
stack<int> order_st;
int comp[NMAX], nrctc;
// graful condensat (temporar folosim unordered_map pentru deduplare si cost minim)
vector< unordered_map<int,int> > adjC; // adjC[i][j] = cost (0 sau 1)
// graful final al componentelor (vecini, cost)
vector<vector<pair<int,int>>> graph_ctc;
// date pentru LCA simplu si dist cost
int nivel[NMAX], tata[NMAX], distC[NMAX];
void citire() {
fin >> N >> M;
int u, v;
for (int i = 0; i < M; ++i) {
fin >> u >> v;
graph[u].push_back(v);
graph_tr[v].push_back(u);
}
fin >> T;
}
// DFS1 iterativ pentru a obține ordinea (finish times)
void kosaraju_first() {
for (int i = 1; i <= N; ++i) viz[i] = 0;
vector<int> it(NMAX, 0);
for (int s = 1; s <= N; ++s) {
if (viz[s]) continue;
// stack of nodes
vector<int> st;
st.push_back(s);
while (!st.empty()) {
int node = st.back();
if (!viz[node]) {
viz[node] = 1;
it[node] = 0;
}
bool pushed = false;
while (it[node] < (int)graph[node].size()) {
int nxt = graph[node][it[node]++];
if (!viz[nxt]) {
st.push_back(nxt);
pushed = true;
break;
}
}
if (!pushed) {
// finished node
order_st.push(node);
st.pop_back();
}
}
}
}
// DFS2 iterativ pe graful transpus pentru a marca componentele
void kosaraju_second() {
for (int i = 1; i <= N; ++i) viz[i] = 1; // reuse: 1 = unprocessed in second pass
nrctc = 0;
while (!order_st.empty()) {
int node = order_st.top(); order_st.pop();
if (!viz[node]) continue;
++nrctc;
// iterative DFS on transposed graph
vector<int> st;
st.push_back(node);
viz[node] = 0; // processed
comp[node] = nrctc;
while (!st.empty()) {
int x = st.back(); st.pop_back();
for (int y : graph_tr[x]) {
if (viz[y]) {
viz[y] = 0;
comp[y] = nrctc;
st.push_back(y);
}
}
}
}
}
int LCA_simple(int a, int b) {
while (a != b) {
if (nivel[a] > nivel[b]) a = tata[a];
else b = tata[b];
}
return a;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
citire();
// Kosaraju
kosaraju_first();
kosaraju_second();
// Construct adjC (deduplicare, pastram cost minim)
adjC.assign(nrctc + 1, unordered_map<int,int>());
for (int u = 1; u <= N; ++u) {
for (int v : graph[u]) {
int cu = comp[u], cv = comp[v];
if (cu == cv) continue;
// muchia cu->cv cu cost 0 (directa)
auto it = adjC[cu].find(cv);
if (it == adjC[cu].end()) adjC[cu][cv] = 0;
else it->second = min(it->second, 0);
// inversa cv->cu cu cost 1
auto it2 = adjC[cv].find(cu);
if (it2 == adjC[cv].end()) adjC[cv][cu] = 1;
else it2->second = min(it2->second, 1);
}
}
// Convertim in vector de vectori pentru iterare rapida
graph_ctc.assign(nrctc + 1, vector<pair<int,int>>());
for (int i = 1; i <= nrctc; ++i) {
graph_ctc[i].reserve(adjC[i].size());
for (auto &p : adjC[i]) {
graph_ctc[i].push_back({p.first, p.second});
}
}
// Initializari pentru tata/nivel/dist
for (int i = 1; i <= nrctc; ++i) {
tata[i] = 0;
nivel[i] = 0;
distC[i] = 0;
}
// Parcurgem (iterativ) fiecare componenta conexa neorientata (sigur e una, dar pentru siguranta)
for (int start = 1; start <= nrctc; ++start) {
if (tata[start] != 0) continue; // deja vizitat
// BFS/DFS iterative (folosim stack)
stack<int> st;
tata[start] = start;
nivel[start] = 0;
distC[start] = 0;
st.push(start);
while (!st.empty()) {
int x = st.top(); st.pop();
for (auto &pr : graph_ctc[x]) {
int y = pr.first;
int cost = pr.second;
if (tata[y] == 0) {
tata[y] = x;
nivel[y] = nivel[x] + 1;
distC[y] = distC[x] + cost;
st.push(y);
}
}
}
}
// Raspuns la interogari
for (int i = 0; i < T; ++i) {
int g, m;
fin >> g >> m;
int cg = comp[g], cm = comp[m];
if (cg == cm) {
fout << 0 << '\n';
continue;
}
int l = LCA_simple(cg, cm);
// cost de la L la B (in jos) + cost de la A la L cand urcam (1 - cost_injos)
int cost_L_to_B = distC[cm] - distC[l];
int up_edges_A_to_L = nivel[cg] - nivel[l];
int cost_A_to_L_when_up = up_edges_A_to_L - (distC[cg] - distC[l]);
int ans = cost_L_to_B + cost_A_to_L_when_up;
fout << ans << '\n';
}
fin.close();
fout.close();
return 0;
}