Интересная теоретическая задача теории графов

Недавно мой отец познакомил меня с трудной проблемой, которую он пытается решить. Исходная проблема возникла при попытке найти оптимальный способ выполнения определенных операций sql. Я перефразирую проблему, чтобы сделать ее более краткой, поскольку меня интересует только теоретический алгоритм, а не конкретная реализация.

Вот мое красочное воссоздание проблемы:

Вам нужно сделать так, чтобы все нравились вам. Вы можете понравиться целевому человеку, подкупив его напрямую или иногда подкупив определенную группу людей, которым вы уже нравитесь, чтобы убедить цель полюбить вас.

Учитывая общее количество людей N и список вариантов подкупа L из K, найдите самый дешевый способ понравиться всем.

Каждый вариант подкупа должен содержать либо

  1. Два числа, первое число представляет человека, которому вы подкупите, чтобы вы ему понравились, а второе число представляет стоимость взятки.
  2. Список чисел, обозначающих группу людей, которых можно подкупить, число, обозначающее человека, которого нужно убедить полюбить вас, и последнее число, обозначающее общую стоимость взятки. Чтобы выполнить групповую взятку, вы должны уже сделать каждого человека в этой группе таким же, как вы.

Вот пример: Люди: 3 Параметры:

  • 1, 10 (вы можете подкупить человека 1, чтобы он вам понравился, за 10)
  • 1, 2, 5 (вы можете подкупить человека 1, чтобы он понравился вам человеку 2, за 5)
  • 2, 7 (вы можете подкупить человека 2, чтобы он вам понравился, за 7)
  • 1, 2, 3, 3 (вы можете подкупить людей 1 и 2, чтобы сделать человека 3 таким же, как вы, за 3)

В этом примере оптимальное решение — использовать первый, второй и четвертый варианты, чтобы вы нравились всем, за общую стоимость 18.

Можете ли вы помочь мне найти обобщенный алгоритм, который подойдет для любого случая?

Конкретных ограничений по количеству нет, но могу сказать, что количество людей почти всегда будет небольшим (< 10), а количество вариантов подкупа может быть очень большим (N * (2^(N-1)) ).

Связанный: это чем-то похоже на проблему 5 CCO 2017.

Unmitigated 10.05.2024 23:44

См. раскраска графиков

user24714692 10.05.2024 23:47

@nate Можете ли вы поделиться соответствующим вопросом/интерпретацией SQL?

Dave 11.05.2024 00:21

@user24714692 user24714692 Как бы вы использовали раскраску графиков для решения этой проблемы?

Dave 11.05.2024 01:33

@Dave Рассматривайте каждого человека как вершину графа. Каждая взятка как грань, связывающая подкупаемого и дающего взятку. Затем вы можете использовать алгоритмы раскраски графов, чтобы найти минимальную стоимость «чтобы все нравились вам», где каждый цвет представляет группу людей, «которые нравятся друг другу», а стоимость представляет собой общую стоимость их подкупа.

user24714692 11.05.2024 01:52

@user24714692 user24714692 Как вы поступаете с взятками группам, как в последнем примере ОП («вы можете подкупить человека 1 и 2, чтобы человек 3 понравился вам, за цену 3)»? Даже если с этим разобраться, как раскрашивание поможет вам решить проблему? Если у вас есть решение, пожалуйста, опубликуйте его.

Dave 11.05.2024 02:29

@Dave Разве мы не можем «раскрасить» человека 1, чтобы он понравился тебе, за цену X? Разве это не проблема раскраски графа? Если вы говорите, что это не так, возможно, это не так. ( ˆ__ )

user24714692 11.05.2024 02:50

Стоит отметить, что эта задача является NP-сложной. Доказательство. Возьмем граф G. Пусть стоимость подкупа любого узла будет равна 1, если вы уже подкупили все узлы, имеющие ребра, к этому узлу, и 10 отдельно. Тогда решение этой проблемы позволит решить en.wikipedia.org/wiki/Feedback_vertex_set, чья задача минимизации NP сложна.

btilly 11.05.2024 20:21
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
8
108
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поскольку n (количество людей) невелико, подход, неэффективный для n, может быть приемлемым.

Давайте подумаем об орграфе вот так. Каждый узел представляет собой состояние, в котором каждый из n человек либо подкуплен, либо не подкуплен. Затем есть 2 ^ n узлов.

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

После того, как веса назначены, остается использовать ваш любимый алгоритм для поиска кратчайшего пути в DAG с (предположительно) неотрицательными весами. https://en.wikipedia.org/wiki/Shortest_path_problem

Так как же нам присвоить эти веса? Вот один из подходов:

Сначала дайте каждому узлу идентификатор, в котором устанавливается i-й бит, если i-й человек подкуплен. Таким образом, узел начального состояния получает идентификатор 0, его дочерние элементы получают идентификаторы с установленным 1 битом и так далее.

Затем свяжите идентификатор, который передается каждой группе, которую можно использовать для взятки, со стоимостью и идентификатором человека, которого нужно подкупить. Поскольку одна группа может быть использована для подкупа нескольких человек, представьте это в виде карты {person_to_bribe => стоимость}.

Затем проанализируйте все узлы в порядке их расстояния от узла 0. Каждая карта узлов создается/обновляется на основе ее предшественников, при этом стоимость каждого узла является минимальной из его карт и карт его предшественников. Как только это будет сделано для глубины i, присвойте соответствующий вес дугам каждого узла глубины i на основе обновленной карты.

Это неэффективно, но поскольку n < 10, все должно быть в порядке.

nodes: 2^n <= 2^9 = 512
arcs: choose(n,0) * choose(n,1) + choose(n,1) + choose(n,2) + ... + choose(n,n-1) * choose(n,n) <= 43,758 (equals this for n=9)

Я думаю, следует явно упомянуть поиск единой стоимости.

Matt Timmermans 11.05.2024 01:36

@MattTimmermans Я, вероятно, что-то упускаю; почему UCS лучше других вариантов?

Dave 11.05.2024 02:36

Это способ сделать то, что вы написали, не создавая экземпляры всех ребер графа.

Matt Timmermans 11.05.2024 02:52

Другие вопросы по теме