Большие входные данные вызывают топологическую сортировку для прекращения работы

1

Вопрос:-

Теперь вы можете пройти онлайн-курсы в Берландском государственном университете! Поликарп должен пройти k основных онлайн-курсов своей специальности, чтобы получить диплом. В общей сложности русские курсы доступны для прохождения.

Ситуация осложняется зависимостью онлайн-курсов, для каждого курса есть список тех, которые должны быть переданы перед началом этого онлайн-курса (список может быть пустым, это означает, что нет никаких ограничений).

Помогите Поликарпу пройти наименьшее количество курсов в общей сложности, чтобы получить специальность (это означает, что нужно пройти все основные и необходимые курсы). Напишите программу, которая печатает порядок курсов.

Поликарп проходит курсы последовательно, он начинает следующий курс, когда заканчивает предыдущий. Каждый курс не может проходить более одного раза.

Входные данные: -

Первая строка содержит n и k (1 ≤ k ≤ n ≤ 105) - количество онлайн-курсов и количество основных курсов специальности Polycarp.

Вторая строка содержит k различных целых чисел от 1 до n - номеров основных онлайн-курсов специальности Polycarp.

Затем следуют n строк, каждый из которых описывает следующий курс: i-й из них соответствует курсу i. Каждая строка начинается с целого числа ti (0 ≤ ti ≤ n - 1) - количество курсов, на которые зависит i-й. Затем следует последовательность ti различных целых чисел от 1 до n - чисел курсов в случайном порядке, от которых зависит i-й. Гарантируется, что ни один курс не может зависеть от самого себя.

Гарантируется, что сумма всех значений ti не превышает 10 ^ 5.

Выход:-

Если это невозможно, -1

Если возможно, затем распечатайте количество курсов, которые должны пройти, а затем порядок, в котором он принимает курсы

Код с комментариями: -

import sys
flag=True
sys.setrecursionlimit(2000000)
c=[];st=[];
def topo(s):#Traversing the array and storing the vertices
    global c,st,flag;
    c[s]=1; #Being Visited
    for i in adjli[s]:#visiting neighbors
        if c[i]==0:
            topo(i)
        if c[i]==1:
            flag=False# If Back Edge , Then Not Possible
    st.append(str(s))
    c[s]=2 # Visited

try:
    n,k=map(int,input().split(' '))#Number Of Courses,Dependencies
    main=list(map(int,input().split(' ')))#Main Dependencies
    depen=[]#Dependencies List
    for i in range(n):
        depen.append(list(map(int,input().split(' ')))[1:]);c.append(0)#Append Input To Dependencies List, Marking Visited as 0(False)
    c.append(0)
    adjli=[]
    adjli.append(main)#Assuming Main Course at index 0 with dependencies as Main Dependency(main)
    for i in range(len(depen)):
        adjli.append(depen[i])#Appending Other Dependencies
    topo(0)#TopoLogical Sort Order
    st.pop(-1)#popping the assumed Main Couse
    if flag:# IF possible then print
        print(len(st))
        print(' '.join(st))
    else:
        print(-1)
except Exception as e:
    print(e,"error")

Что я сделал?

Я сделал топологическую сортировку и сохранил порядок обхода. Я предположил, что курс специальности хранится в индексе 0 и соответствующим образом формирует график. Если встретился BackEdge, я вернулся -1.

В чем проблема?

Код дал правильный вывод для небольших входов, но столкнулся с Runtime Error в случае больших Входов, например: -

Код для генерации ввода: -

print(100000,1)
print(100000)
for i in range(100000):
  if i==0:
    print(i)
  else:
    print(1,i)

Что я сделал, чтобы решить эту проблему?

Я попытался распечатать ошибку времени выполнения, но ничего не отображалось.

Ссылка на вопрос: - Вопрос

Мое решение: - Решение

Теги:
python-3.x
algorithm
runtime-error
graph-theory

1 ответ

1
Лучший ответ

Это проблема с стеком во время рекурсии. Python имеет ограниченную лимиту рекурсии, даже если вы указали этот предел явно. Эта проблема упоминается в этом блоге Codeforces: https://codeforces.com/blog/entry/45135/

Одним из решений является реализация функции topo с использованием итеративного подхода, а не рекурсивного подхода.

Измененный код может быть:

import sys
flag=True
sys.setrecursionlimit(2000000000)
c=[];st=[];
cur_adj=[]
def topo(s):#Traversing the array and storing the vertices
    global c,st,flag;
    stack = [s]
    while(stack):
        s = stack[-1]
        c[s]=1; #Being Visited
        if(cur_adj[s] < len(adjli[s])):
            cur = adjli[s][cur_adj[s]]
            if(c[cur]==0):
                stack.append(cur)
            if(c[cur]==1):
                flag=False# If Back Edge , Then Not Possible
            cur_adj[s]+=1
        else:
            c[s]=2
            st.append(str(s))
            del stack[-1]

try:
    n,k=map(int,input().split(' '))
    main=list(map(int,input().split(' ')))
    depen=[]
    for i in range(n):
        depen.append(list(map(int,input().split(' ')))[1:]);c.append(0)
        cur_adj.append(0)
    c.append(0)
    cur_adj.append(0)
    adjli=[]
    adjli.append(main)#Assuming Main Course at index 0 with dependencies as Main Dependency(main)
    for i in range(len(depen)):
        adjli.append(depen[i])#Appending Other Dependencies
    topo(0)#TopoLogical Sort Order
    st.pop(-1)#popping the assumed Main Couse
    if flag:# IF possible then print
        print(len(st))
        print(' '.join(st))
    else:
        print(-1)
except Exception as e:
    print(e,"error")

Этот код реализует то, что делает стек во время рекурсии. cur_adj - это список, где cur_adj [i] содержит индекс я соседнего узла для посещения следующего. Когда все я соседние узлы посещаются, я выворачивается из стека (стек - это обычный список, который имитирует стек рекурсии).

  • 0
    Спасибо за помощь. Я застрял с этой ошибкой с тех пор, как запустил Graphs (особенно dfs из-за рекурсии). Блог был действительно полезным, и ваш ответ был таким же. Однако я хотел бы знать, почему Python не смог решить эту проблему? Разве это не так уж важно?
  • 0
    Я думаю, что некоторые языки могут не дать вам свободу делать некоторые вещи только потому, что они потенциально вредны. Например, в Java вы должны явно привести значение с плавающей запятой к int, прежде чем присваивать его переменной int. Но C / C ++ дает вам свободу зависеть от неявного приведения. То же самое относится к Python против C / C ++ в пределе стека рекурсии.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню