>>221173737 Он кладёт туда вершины, которое были покрашены или у них изменились метки, то есть вершины повторяются. Он может взять покрашенную вершину и что-нибудь запороть, но я же подсознательно понимаю, что это бред, но доказать не могу...
>>221174079 Но блять я всё равно сомневаюсь, у меня уже на этой почве крыша подтекает. Я знаю, что у помеченных вершин метки не увеличиваются, но он может у других запороть... Хоть это и невозможно, но исключать такую ситуацию нельзя.
>>221174503 1. Неговорящие названия переменных 2. Директива using namespace Хотя в твоем случае простительно, иначе у тебя двух мониторов не хватит это читать
>>221174503 Однобуквенные переменные, громоздкие непонятные типы. Типы лучше затайпдефить в что-нибудь с нормальными именами, переменные тоже нормально обозвать
>>221174503 Да нормально там всё, анон выше просто промпрог петух, не слушай его. Олсо вместо того, чтобы спрашивать советов на дваче гугляй как устроены stl структуры и очередь твоя конкретно - и будет тебе счастье.
>>221174728 1.Ну да, а потом читаешь в ворнингах компилятора "variable 'fake_a' set but not used" и охуеваешь Тру стори, stb_image, хотя на сях своя атмосфера. 2. Выше ответили
Проблем из-за выделенной строчки не будет. Код скорее всего не скомпилируется потому что Q.top() вернет std::pair, а не int. Если что-то не работает пиши, посмотрим поподробнее. Про стиль кода сейчас распишу в следующем сообщении.
>>221176073 Итак, поехали. >>221176105 Мне в общем-то похуй лаба это или не лаба, может кому полезно будет.
Первая проблема, которая бросается в глаза конечно это using namespace std. Это плохая практика, как заметили уже некоторые аноны. Библиотеки могут переопределять некоторые названия из std и использование неймспейса приведет к конфликтам. Это довольно неприятный класс проблем. Я бы рекомендовал просто приучить себя никогда не использовать using namespace std.
>>221177092 Дальше идет стиль названий переменных. Рекомендуется использовать один стиль для читаемости. Допустим называть все переменные с маленькой буквы и каждое новое слово с большой: distancesFromSrc. Или все переменные маленькими буквами с подчеркиванием между ними: distances_from_src. Это становится очень важно при увеличении количества кода. Единый стиль помогает быстрее понимать к чему относится имя.
Сами названия переменным стоит давать отражающие их суть. Опять же для упрощения понимания. G -> distance_matrix, d-> distances_form_source, Q -> distance_to_vertex_queue, вроде того.
>>221177348 Да... Вместо своей queue используешь принтабл, getCont вернёт контейнер(у тебя вектор с парами будет), дальше делаешь с ним че хочешь. Пиздец вы, из-за вас пришлось КОД ПИСАТЬ, копипасту с цппреф не можете под себя адаптировать, рря поп контейнер очистит, кому не похуй?
>>221177317 Рассмотрим типы переменных. В коде и для вершин и для дистанций используется int. Это приводит к возможным проблемам, например с тем, чтобы понять что является чем в std::pair<int, int>. Оптимальным вариантом было бы использование типов, которые бы не разрешили свободный каст между собой. Но для компактности можно использоать менее безопасный, но более простой вариант - using. Он не оградит от некорректного присвоения вершине дистанции или наоборот, но поможет понять что имелось в виду авотором. Сравните: std::pair<int, int> и std::pair<vertex_t, distance_t>. Пара строк типа using vertex_t = int; и using distance_t = int; уже улучшают читаемость.
И не используйте typedef, он устарел. Используйте using.
>>221177443 Вот тебе пример плохого стиля. Чтобы понять, что имел в виду анон, мне пришлось лезть в документацию priority_queue, от которой он наследовался и узнать, что protected! член, к которому имеет доступ разработчик называется блядь 'c' и, оказывается, хранит контейнер.
>>221177647 Остановимся на используемых структурах. Для читаемости можно было бы сделать using dist_and_vertex = std::pair<distance_t, vertex_t>. Тогда получаем std::priority_queue<dist_and_vertex, std::vector<dist_and_vertex>, std::greater<dist_and_vertex>>. Это все еще довольно громоздко, но уже чуть проще чем куча пар.
Но давайте посмотрим на использование пары самой по себе. Вообще std::pair плоха тем, что ее поля называются first и second. Это ни о чем не говорящее название. Обычная структура была бы более читаемой: struct VertexDist { vertex_t vert = 0; distance_t dist = 0; }; Сравните dist_queue.top().first и dist_queue.top().vert - сразу понятно какое значение мы хотим получить и не нужно разгадывать что такое first.
>>221178170 Теперь про очередь. Начнем с того, что вместо queue.push(std::make_pair(a, b,)) можно использовать queue.emplace(a, b) - гораздо приятнее и компактнее.
std::priority_queue, вообще говоря, я не могу назвать особенно хорошим контейнером. У нее довольно неудобный интерфейс и потенциально проблемы с производительностью. Так как низлежащий контейнер это вектор при добавлении он может расширяться, а это занимает много времени. Для чего вообще используется приоритетная очередь? Ради O(1) доступа к макс элементу и O(log_n) вставки и удаления. Знаете что еще обладает таким же свойством? std::set, при этом он удобнее и по нему можно итерироваться без извращений, которыми занимались аноны в сообщениях выше. Потенциально он быстрее - std::set не занимается релокациями, в нем нет непрерывного хранилища. Стоит проверить, не будет ли он быстрее. Но я бы рекомендовал его больше, чем std::priority_queue если это не приведет к явным проблемам с производительностью.
На этом пожалуй все. Это не все проблемы с std::priority_queue, но на них подробнее останавливаться не станем.
>>221178753 >Знаете что еще обладает таким же свойством? std::set, при этом он удобнее и по нему можно итерироваться без извращений, которыми занимались аноны в сообщениях выше. Вот только в set не может быть одинаковых ключей... А реаллокация в векторе раз в 500 лет происходит, если его достаточно большим взять...
>>221178308 Он пишется довольно просто: bool operator<(const VertexDist& that) const { return std::tie(distance, vertex) < std::tie(that->distance, that->vertex); }
Но я бы скорее всего рекомендовал использовать свой оператор определенный около самой очереди. Дело в том, что сравнение дистанции в первую очередь не является важным свойством для общего оператора сравнения, но очень важно для конкретно этой очереди. Это опасно, поэтому лучше определить оператор специально для использования в очереди. Это лишнее в данном коде, где структура может быть определена рядом с очередью, но в реальных проектах поможет избежать возможных проблем.
>>221173385 (OP) хуйня какая-то, у тебя в куче должны быть элементы уникальны по ключу и только делаться decrease_key если найден путь короче, ты делаешь пуш в кучу не проверяя не хуйню ли ты туда засовываешь, мб там уже путь есть лучше, вот набросал примерный код на непонятном языке:
void dijkstra(from) { var remaining_vertices = new Heap(vertices); remaining_vertices[from] = 0; while (remaining_vertices.any()) { var min = remaining_vertices().pop(); dist[min.id] = min.key; for (var v in edges[min.id]) { remaining_vertices.decrease_key(v.id, min.key + v.weight); } }
>>221178967 В данном случае нет смысла в неуникальных парах вершина/дистанция. Про взять вектор согласен, но нужно сначала отнаследоваться от std::priority_queue и выделить память. Довольно громоздко и если не оправдывается производительностью, то нет смысла. Конечно же все нужно замерять.
>>221179492 >В данном случае нет смысла в неуникальных парах вершина/дистанция Почему... >но нужно сначала отнаследоваться от std::priority_queue и выделить память. Что... Я имел ввиду взять вектор как underlying контейнер в prioirity_queue... Куда наследоваться... Зачем...
>>221178205 Код стандартной библиотеки плюсов это не пример читаемости и там есть специальные ограничения и исторические причины. Для обычного же кода то, что я расписал, является стандартными вещами. Все мои комментарии вполне применимы и к реальным проектам.
>>221179587 Вектор и так ялвяется underlying контейнером стандартно. Для того, чтобы получить доступ к экземпляру используемого вектора придется наследоваться, так как он protected. См. >>221177257
>>221179929 Это следует из логики алгоритма - берем вершину с самым коротким известным расстоянием и смотрим расстояния от нее. Если мы добавим в очередь одну и ту же вершину и расстояние, то мы просто два раза рассмотрим одни и те же пути из нее - это не имеет смысла.
>>221180760 Да причём тут контейнер... В графе не может быть разных вершин с одинаковым именем и расстоянием до данной, если по какой-то причине мы такую записали, хотя у нас уже есть такая, то алгоритм неправильный...
>>221181150 В графе нет, в очереди может появиться одна и та же вершина с разными расстояниями: рассмотрим ребра a, b c С расстояниями: a->c 5 a->b 3 b->c 1 Начиная из a в очередь добавятся: c, 5 b, 3 По приоритету будет взята b, из b идет ребро в c, тогда в очередь добавится c, 4: c, 4 c, 5 У нас возникло повторение вершины в очереди. Мы могли бы избежать этого если бы был простой способ определить, что c уже в очереди и поменять его приоритет. Этого в стандартной приоритетной очереди сделать нельзя.
>>221181623 >У нас возникло повторение вершины в очереди. Не повторение вершины, а повторение пары (вершина, расстояние)... >В графе не может быть разных вершин с одинаковым именем и расстоянием
>>221181920 Погоди, но приоритет-то это расстояние как раз, там могут быть вершины с разными именами и одинаковыми расстояниями, сет точно не подойдёт.
>>221182402 Приоритет это расстояние в алгоритме. В коде приоритет это пара расстояние/номер вершины. Пара сравнивается сначала по расстоянию, потом по номеру вершины, поэтому приоритетеная очередь и срабатывает. Set сработает точно так же. Ключом выступает пара, а не только расстояние.
Конкретные проблемы читаемости кода, которые и приводят к такому недопониманию я рассмотрел здесь, кстати: >>221179150