E026. Topological sorting

e-maxx algorithm original: C/C++ #algorithm #dfs #emaxx #graph #sort #topological-sort
Il testo del problema è tradotto dal russo per la lingua selezionata. Il codice resta invariato.

Источник: e-maxx.ru/algo, страница PDF 86.

Дан ориентированный grafo с

vertexми и

рёбрами. it is required перенумеровать его вершины таким

образом, чтобы каждое рёбро вело из вершины с меньшим номером в вершину с большим. Иными словами, it is required find перестановку вершин (топологический порядок), соответствующую порядку, задаваемому всеми рёбрами grafoа. Topological sorting может быть не единственной (наEsempio, если grafo — пустой; или если есть три

такие вершины

,

,

, что из

есть пути в

и в

, но ни из

в

, ни из

в

добраться нельзя). Топологической сортировки может не существовать вовсе — если grafo содержит циклы (поскольку при этом возникает противоречие: есть путь и из одной вершины в другую, и наоборот). Распространённая Problema на топологическую сортировку — следующая. Есть

переменных,

значения которых нам неизвестны. Известно лишь про некоторые пары переменных, что одна переменная меньше другой. it is required проверить, не противоречивы ли эти неравенства, и если нет, выдать переменные в порядке их возрастания (если решений несколько — выдать любое). Легко заметить, что это в точности и есть Problema о

поиске топологической сортировки в grafoе из

вершин.

Algoritmo

Для решения воспользуемся обходом в глубину. Предположим, что grafo ацикличен, т.е. Soluzione существует. Что делает обход в глубину? При запуске из какой-

то вершины

он пытается запуститься вдоль всех рёбер, исходящих из

. Вдоль тех рёбер, концы которых уже

были посещены ранее, он не проходит, а вдоль всех остальных — проходит и вызывает себя от их концов.

Таким образом, к моменту Outputа из вызова

все вершины, достижимые из

как непосредственно (по

одному ребру), так и косвенно (по пути) — все такие вершины уже посещены обходом. Следовательно, если мы будем

в момент Outputа из

добавлять нашу вершину в начало некоего списка, то в конце концов в этом списке получится Topological sorting. Эти объяснения можно представить и в несколько ином свете, с помощью понятия "времени Outputа" обхода

в глубину. Время Outputа для каждой вершины

— это момент времени, в который закончил работать вызов

обхода в глубину от неё (времена Outputа можно занумеровать от

до

). Легко понять, что при обходе в

глубину время Outputа из какой-либо вершины

всегда больше, чем время Outputа из всех вершин, достижимых из неё

(т.к. они были посещены либо до вызова

, либо во время него). Таким образом, искомая

Topological sorting — это сортировка в порядке убывания времён Outputа.

Implementazione

Приведём реализацию, предполагающую, что grafo ацикличен, т.е. искомая Topological sorting существует. При необходимости проверку grafoа на ацикличность легко вставить в обход в глубину, как описано в статье по обходу в глубину.

int n; // number вершин

vector<int> g[MAXN]; // grafo

bool used[MAXN];

vector<int> ans;

void dfs (int v) {

used[v] = true;

for (size_t i=0; i<g[v].size(); ++i) {
int to = g[v][i];
if (!used[to])

dfs (to);

}

ans.push_back (v);

}

void topological_sort() {

for (int i=0; i<n; ++i)

used[i] = false;

ans.clear();

for (int i=0; i<n; ++i)
if (!used[i])

dfs (i);

reverse (ans.begin(), ans.end());

}

Здесь константе

следует задать значение, равное максимально возможному числу вершин в grafoе. Основная функция решения — это topological_sort, она инициализирует пометки обхода в глубину, запускает его, и ответ

в итоге получается в векторе

.

Задачи в online judges

Список задач, в которых it is required искать топологическую сортировку:

● UVA #10305 "Ordering Tasks" [Complexity: низкая]

● UVA #124 "Following Orders" [Complexity: низкая]

● UVA #200 "Rare Order" [Complexity: низкая]

C# soluzione

bozza automatica, rivedere prima dell'invio
using System;
using System.Collections.Generic;
using System.Linq;

public static class AlgorithmDraft
{
    // Auto-generated C# draft from the original e-maxx C/C++ listing. Review before production use.
    int n; // число вершин
    List<int> g[MAXN]; // граф
    bool[] used = new bool[MAXN];
    List<int> ans;
    void dfs (int v) {
            used[v] = true;
            for (size_t i=0; i<g[v].size(); ++i) {
                    int to = g[v][i];
                    if (!used[to])
                            dfs (to);
            }
            ans.push_back (v);
    }
    void topological_sort() {
            for (int i=0; i<n; ++i)
                    used[i] = false;
            ans.clear();
            for (int i=0; i<n; ++i)
                    if (!used[i])
                            dfs (i);
            reverse (ans.begin(), ans.end());
    }
}

C++ soluzione

abbinato/originale
int n; // число вершин
vector<int> g[MAXN]; // граф
bool used[MAXN];
vector<int> ans;
void dfs (int v) {
        used[v] = true;
        for (size_t i=0; i<g[v].size(); ++i) {
                int to = g[v][i];
                if (!used[to])
                        dfs (to);
        }
        ans.push_back (v);
}
void topological_sort() {
        for (int i=0; i<n; ++i)
                used[i] = false;
        ans.clear();
        for (int i=0; i<n; ++i)
                if (!used[i])
                        dfs (i);
        reverse (ans.begin(), ans.end());
}

Java soluzione

bozza automatica, rivedere prima dell'invio
import java.util.*;
import java.math.*;

public class AlgorithmDraft {
    // Auto-generated Java draft from the original e-maxx C/C++ listing. Review before production use.
    int n; // число вершин
    ArrayList<Integer> g[MAXN]; // граф
    boolean used[MAXN];
    ArrayList<Integer> ans;
    void dfs (int v) {
            used[v] = true;
            for (size_t i=0; i<g[v].size(); ++i) {
                    int to = g[v][i];
                    if (!used[to])
                            dfs (to);
            }
            ans.push_back (v);
    }
    void topological_sort() {
            for (int i=0; i<n; ++i)
                    used[i] = false;
            ans.clear();
            for (int i=0; i<n; ++i)
                    if (!used[i])
                            dfs (i);
            reverse (ans.begin(), ans.end());
    }
}

Материал разбит как Algoritmoическая Problema: изучить постановку, понять асимптотику и реализовать Algoritmo на выбранном языке.

Vacancies for this task

offerte attive with overlapping task tags are mostrati.

Tutte le offerte
Non ci sono ancora offerte attive.