Course Schedule II
Este problema es equivalente a Minimal Labels de Codeforces. Tratamos la “etiqueta” de un vértice en “Minimal Labels” como el tiempo de finalización de un curso en “Course Schedule II”. Así que alcanza con resolver el problema de CF (análisis ) y luego imprimir la permutación inversa .
Implementación
Complejidad temporal:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<int> out(n + 1); // Cantidad de nodos salientes
vector<vector<int>> radj(n + 1); // Grafo inverso
for (int i = 0; i < m; i++) {
int a, b;
cin >> a >> b;
radj[b].push_back(a);
out[a]++;
}
/*
* Cualquier nodo con out[i] == 0 se puede usar, así que guardamos todos los
* nodos posibles en un max-heap para obtener el nodo con el id máximo.
*/
priority_queue<int> pq;
for (int i = 1; i <= n; i++) {
if (out[i] == 0) { pq.push(i); }
}
vector<int> ans;
while (pq.size()) {
// Sacar el nodo con el id más grande.
int x = pq.top();
pq.pop();
ans.push_back(x);
// Quitar todas las aristas que empiezan en `x`.
for (int t : radj[x]) {
out[t]--;
if (!out[t]) { pq.push(t); }
}
}
reverse(ans.begin(), ans.end());
for (int t : ans) { cout << t << " "; }
}import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) {
Kattio io = new Kattio();
int n = io.nextInt();
int m = io.nextInt();
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i <= n; i++) { graph.add(new LinkedList<>()); }
for (int i = 0; i < m; i++) {
int a = io.nextInt();
int b = io.nextInt();
graph.get(b).add(a);
}
// Calcular el grado de entrada de cada nodo.
int[] inDegree = new int[n + 1];
for (int i = 1; i <= n; i++) {
for (int to : graph.get(i)) { inDegree[to]++; }
}
/*
* Cualquier nodo con grado de entrada 0 se puede usar, así que guardamos todos
* los nodos posibles en un max-heap para obtener el nodo con el id máximo.
*/
PriorityQueue<Integer> possibleNodes =
new PriorityQueue<>(Comparator.reverseOrder());
for (int i = 1; i <= n; i++) {
if (inDegree[i] == 0) { possibleNodes.add(i); }
}
List<Integer> ans = new ArrayList<>();
while (!possibleNodes.isEmpty()) {
// Sacar el nodo con el id más grande.
int node = possibleNodes.remove();
ans.add(node);
// Quitar todas las aristas que empiezan en `node`.
for (int to : graph.get(node)) {
if (--inDegree[to] == 0) { possibleNodes.add(to); }
}
}
for (int i = n - 1; i >= 0; i--) { io.print(ans.get(i) + " "); }
io.close();
}
// CodeSnip{Kattio}
}import heapq
n, m = map(int, input().split())
out = [0] * (n + 1) # Cantidad de nodos salientes
radj = [[] for _ in range(n + 1)] # Grafo inverso
for _ in range(m):
a, b = map(int, input().split())
radj[b].append(a)
out[a] += 1
ans = []
pq = []
for i in range(1, n + 1):
if out[i] == 0:
# Cualquier nodo con out[i] == 0 se puede usar, así que guardamos todos
# los nodos posibles en un max-heap para obtener el nodo con el id máximo.
heapq.heappush(pq, -i)
while pq:
x = -heapq.heappop(pq) # Sacar el nodo con el id más grande.
ans.append(x)
for t in radj[x]:
out[t] -= 1
if out[t] == 0:
heapq.heappush(pq, -t) # Quitar todas las aristas que empiezan en `x`.
print(" ".join(str(i) for i in reversed(ans)))