Skip to Content

Constrained Topological Sort

Solución 1

Editorial oficial (sin código) 

Complejidad temporal: O(M+NlogN)\mathcal{O}(M+N\log N)

#include <bits/stdc++.h> using namespace std; void fail() { cout << "No\n"; exit(0); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N, M; cin >> N >> M; vector<vector<int>> out(N), in(N); for (int i = 0; i < M; ++i) { int s, t; cin >> s >> t; --s, --t; out.at(s).push_back(t); in.at(t).push_back(s); } // hallamos un orden topológico vector<int> order; vector<int> indeg(N); for (int i = 0; i < N; ++i) { indeg.at(i) = size(in.at(i)); if (!indeg.at(i)) order.push_back(i); } for (int i = 0; i < size(order); ++i) { int s = order.at(i); for (int t : out.at(s)) { if (!(--indeg.at(t))) order.push_back(t); } } if (size(order) != N) fail(); struct Bound { int l, r; }; vector<Bound> bounds(N); for (auto &b : bounds) cin >> b.l >> b.r; for (int i = N - 1; i >= 0; --i) { int t = order.at(i); for (int s : in.at(t)) bounds.at(s).r = min(bounds.at(s).r, bounds.at(t).r - 1); } // asignamos etiquetas en orden using pi = pair<int, int>; priority_queue<pi, vector<pi>, greater<pi>> by_l, by_r; // para cada vértice i no asignado con grado de entrada 0 // guardamos o bien {l[i], i} en by_l o {r[i], i} en by_r for (int i = 0; i < N; ++i) { indeg.at(i) = size(in.at(i)); if (!indeg.at(i)) by_l.push({bounds.at(i).l, i}); } vector<int> P(N); for (int p = 1; p <= N; ++p) { while (!by_l.empty() && by_l.top().first <= p) { // pasamos de by_l a by_r int v = by_l.top().second; by_l.pop(); by_r.push({bounds.at(v).r, v}); } if (by_r.empty() || by_r.top().first < p) fail(); int v = by_r.top().second; by_r.pop(); P.at(v) = p; for (int t : out.at(v)) { if (!(--indeg.at(t))) by_l.push({bounds.at(t).l, t}); } } cout << "Yes\n"; for (int i = 0; i < N; ++i) cout << P.at(i) << " "; }