Advertisement
nq1s788

Untitled

Dec 22nd, 2024
42
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.78 KB | None | 0 0
  1. Давайте посмотрим на задачу как на графовую задачу. У нас есть вершины (солдаты), и ориентированный граф, где из вершины x идет ребро в y, если солдат под номером x выше солдата под номером y. Нам нужно упорядочить солдатов так, чтобы никакой солдат слева не был выше солдата справа, то есть чтобы для любого известного ребра (x, y) x шло раньше чем y. Все ребра в нашем построении должны идти направо. А так же заметим, что такое построение в целом возможно, только если в графе нет циклов.
  2.  
  3. Если в графе всё таки нет циклов, он представляет собой набор деревьев. В каждом дереве корень -- самый высокий солдат из всех, с которыми связан либо он либо связанные с ним солдаты. Если мы начнем обходить дерево dfs-ом из него, то в каждую вершину в дереве мы зайдем только после ее родителя (солдата выше), и получается что каждую вершину мы посетим после вершины, которая должна стоять раньше нее в ответе. Тогда для этого дерева нам достаточно взять вершины в ответ в порядке их обхода dfs-ом из корня. Такое упорядочивание вершин называется Топологическая сортировка. Так как деревья между собой не связаны ребрами, нам неважно в каком порядке относительно друг друга в ответе будут находиться вершины из разных деревьев, поэтому просто выпишем каждое дерево по порядку.
  4.  
  5. Итого:
  6. 1) Проверим граф на ацикличность, если циклы есть ответ "No". Про проверку графа на ацикличность можно почитать здесь http://e-maxx.ru/algo/finding_cycle
  7. 2) Найдем все корни -- это будут вершины, в которых не идет ни одно ребро
  8. 3) Запустим dfs из каждого корня, запишем в ответ вершины в порядке посещения
  9.  
  10. Пример кода на python:
  11. def dfs(h):
  12.     used[h] = 1
  13.     answ.append(h + 1)
  14.     for e in g[h]:
  15.         if used[e] == 1:
  16.             print('No') #пытаемся пойти в нашего родителя (вершину, из поддерева которой еще не вышли)
  17.             exit(0)
  18.         if used[e] == 0:
  19.             dfs(e)
  20.     used[h] = 2 #обошли всё поддерево, "закрываем" вершину
  21.  
  22.  
  23. n, m = map(int, input().split())
  24. g = [set([]) for i in range(n)] #set чтобы убрать повторы
  25. is_root = [True] * n
  26. for i in range(m):
  27.     x, y = map(int, input().split())
  28.     x -= 1
  29.     y -= 1
  30.     is_root[y] = False
  31.     g[x].add(y)
  32. used = [0] * n
  33. answ = []
  34. for i in range(n):
  35.     if is_root[i]:
  36.         dfs(i)
  37. if False in used: #если кого-то не посетили, значит есть компонента, которая полностью цикл (у нее нет "корня")
  38.     print('No')
  39. else:
  40.     print('Yes')
  41.     print(*answ)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement