Блог пользователя MiptLited

Автор MiptLited, 4 года назад, По-русски

Приглашаем всех желающих принять участие в чемпионате по алгоритмическому программированию, приуроченном к 10-летию Центра развития ИТ-образования МФТИ.

Чемпионат пройдет в двух дивизионах: A/B и C/D. Задачи контеста подготовили преподаватели МФТИ и СПбГУ.

Участвовать в чемпионате можно как в команде до 3-х человек, так и в одиночку.

Зарегистрироваться на чемпионат можно по ссылке: https://clck.ru/SHb6p

16 декабря Центр развития ИТ-образования МФТИ (ЦРИТО) отмечает 10-летний юбилей. Открытый чемпионат 6 декабря — одна из образовательных инициатив ЦРИТО, которая наряду с другими текущими проектами в области ИТ помогает десяткам тысяч молодых и опытных специалистов из России и зарубежных стран в профессиональном и карьерном росте.

  • Проголосовать: нравится
  • +33
  • Проголосовать: не нравится

»
4 года назад, # |
  Проголосовать: нравится +15 Проголосовать: не нравится

А вы можете опубликовать расписание, ссылку на вход в тестирующую систему?

»
4 года назад, # |
  Проголосовать: нравится +16 Проголосовать: не нравится

Будет ли открыто дорешивание? Спасибо!

»
4 года назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится

А есть где-нибудь обсуждение задач?

Например, как решать задачу F? Верно ли, что можно k раз запускать Дейкстру, после каждого прохода обновляя веса ребер? Это получило WA5 — то ли из-за плохой реализации, то ли из-за неправильной идеи (в таком случае хотелось бы увидеть контрпример).

И дайте ссылку на дорешивание, пожалуйста,

  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится +8 Проголосовать: не нравится

    В том же контесте. В обоих дивизионах.

  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится +8 Проголосовать: не нравится

    По F запускали min-cost-max-flow по следующему графу: Каждое ребро дублируем k раз (каждое пропускной способностью 1, а цена каждого следуюущего увеличивается на 1). Восстанавливаем ответом k раз запускаем dfs по ребрам с потоком. Ну и аккуратно обработать самый первый поток, ибо цена 0 (мы еще в цену добавили количество ребер по которым прошли)

  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Тест 5:

    Картинка
    Входные данные

    Ответ — 51: сходить по три раза по каждому из трёх понятных маршрутов. Видимо, Дейкстра оступается, а потом, в отличие от потока, не может отменить свою ошибку.

    Решение жюри — min-cost max-flow с сетью из $$$n \cdot n \cdot k$$$ рёбер — то же, что в комментарии Zool. С Фордом-Беллманом $$$50^5$$$, если вдруг не успевает — есть много возможных оптимизаций: например, break в Форде-Беллмане, или учесть, что для каждого дополняющего пути у каждого мультиребра интересны не все $$$k$$$ стоимостей, а только парочка. И действительно есть проблема с нулевыми рёбрами при восстановлении пути. У нас она решается отменой не одного, а двух парных рёбер при проходе по ребру в любую сторону.

    • »
      »
      »
      4 года назад, # ^ |
        Проголосовать: нравится +18 Проголосовать: не нравится

      Можно поподробнее про проблему? У меня никаких костылей в коде нет (у меня правда и граф другой — рёбра можно не раскопировать, а просто стоимость считать в зависимости от текущего потока).

      • »
        »
        »
        »
        4 года назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

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

        У меня в реализации каждое ребро $$$(u, v, cost)$$$ расчетверяется:
        $$$u \xrightarrow[1]{+cost} v$$$, $$$v \xrightarrow[0]{-cost} u$$$, $$$v \xrightarrow[1]{+cost} u$$$, $$$u \xrightarrow[0]{-cost} v$$$.
        Если, например, прошли по первому из этих четырёх рёбер — делаю все пропускные способности нулями, кроме второго ребра — которое отменяет первое. Ну и возвращаю, если прошли обратно.

        • »
          »
          »
          »
          »
          4 года назад, # ^ |
            Проголосовать: нравится +18 Проголосовать: не нравится

          Никогда не выгодно ходить по одному и тому же ребру в две разные стороны. Более того, если вы разрешаете так делать, то вы формально даже нарушаете модель задачи (допустим вы 5 раз прошли в одну сторону, потом решили пойти в другую: в модели задачи это стоит 5, в вашей сети — 0). Это, конечно, неважно, потому что, опять же, никогда не выгодно ходить по одному ребру в разные стороны.

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

          • »
            »
            »
            »
            »
            »
            4 года назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится

            Согласен с первым абзацем.

            А про второй абзац — не понимаю, как сделать два ребра, а не четыре, но чтобы у них были правильные стоимости. Нам же нужно уметь для каждой цены $$$x$$$:

            • пойти $$$u \rightarrow v$$$ или $$$v \rightarrow u$$$ с ценой $$$x$$$,
            • отменить любое из этих рёбер с ценой $$$-x$$$.

            Это четыре ребра, а не два.

            Понятно, как делать, если пересчитывать стоимость на лету: на каждом ребре поддерживать поток по нему. Тогда проблемы и нет. Но мы же сейчас про другое решение, которое сначала строит сеть, а потом пускает на ней обычный min-cost max-flow без хаков.

            • »
              »
              »
              »
              »
              »
              »
              4 года назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится

              Окей, видимо я неправильно понял о чем речь. Я говорил про решение, которое пересчитывает стоимость в зависимости от потока.