Спасибо, задача решена!
№ | Пользователь | Рейтинг |
---|---|---|
1 | tourist | 4009 |
2 | jiangly | 3823 |
3 | Benq | 3738 |
4 | Radewoosh | 3633 |
5 | jqdai0815 | 3620 |
6 | orzdevinwang | 3529 |
7 | ecnerwala | 3446 |
8 | Um_nik | 3396 |
9 | ksun48 | 3390 |
10 | gamegame | 3386 |
Страны | Города | Организации | Всё → |
№ | Пользователь | Вклад |
---|---|---|
1 | cry | 167 |
2 | Um_nik | 163 |
3 | maomao90 | 162 |
3 | atcoder_official | 162 |
5 | adamant | 159 |
6 | -is-this-fft- | 158 |
7 | awoo | 157 |
8 | TheScrasse | 154 |
9 | Dominater069 | 153 |
9 | nor | 153 |
Название |
---|
Задача о минимальном остовном дереве решается двумя алгоритмами - Крускала и Прима. Оба алгоритма находят минимальные деревья, которые минимальны не только по сумме весов всех ребер, но и по весу максимального ребра. (минимальное остовное дерево является минимальным и в таком смысле) но не всякое дерево, обладающего такими свойствами, является минимальным остовным деревом, отсюда можно предположить, что предложенную задачу возможно решать за время O(n + m) (O(V + E) ) Прима и Крускала можно реализовать за N Log N, где N = V+E (можно и поточнее оценки строить, ну да неважно, главное присутствие логарифма. возможно в данной задаче можно обойтись без него.
А ну все понятно. нам нужно добавить первые k рёбер, взятые из сортированного массива, но массив мы сортить не будем, а будем искать это K с помощью бинпоиска, и одновременно делать что-то вроде порядковой статистика (как в QSort) то есть делить массив на две части, чтобы в первой половине все числа были не больше чем во второй, получим Log(E) + E.
давай на примере чтобы понятнее было.
вот у нас есть массив из 100 рёбер. запустим функцию которая поделит его на две части по 50 рёбер, в первой части вссе рёбра меньше либо равны по весу, чем во второй части.
добавим все рёбра перовй половины в DSU, если граф стал связным, то отбрасываем вторую половину, ревертим все операции с DSU что мы только что сделали, и запускаем такую функцию от первой части массива. иначе оставляем рёбра в DSU, и запускаем функцию от второй половины массива.
На самом деле, можно просто запоминать всю структуру DSU перед её изменением на одной итерации, а потом, если надо, то откатывать её к предыдущей версии. Все равно получится линейное время.Там же написано: используйте какую-то жесть из предыдущего задания. Кормен врать не будет - сказал за линейное время решается, значит за линейное.
Идея примерно в следующем:
Находите медианное ребро, то есть такое, которое стояло бы в середине списка отсортированных по весу ребер. Затем строите граф, который состоит только из ребер, которые не больше по весу, чем это медианное. С помощью dfs узнаете является граф связным или нет. Дальше в зависимости от этого, либо добавляете навсегда в граф ребра, меньшие медианы, и сдвигаете левую границу на минимальное используемое ребро, либо просто сдвигаете правую границу, ничего не добавляю в граф. Получается что-то типа бинпоиска.
Утверждается, что при аккуратной реализации того, что я описал получится примерно то, что нужно и все за линейное время(O(n+m)).
UPD: O(n + m)
При реализации нужно очень аккуратно красить компоненты связности и отменять раскраску примерно таким же методом запоминания, который *Alias* написал выше про DSU.
и да, возможно можно аккуратно все сделать, за линию, удаляя рёбра по которым дфс уже прошёл.
Делаете что-то типа бинпоиска по количеству ребер, которых достаточно для того, чтобы граф стал связным. Изначально левая граница этого числа равна, видимо, одному ребру, а правая - числу ребер(если, конечно, вообще гарантируется, что граф из всех ребер связный). Эти границы - два числа L и R. Пока они не сойдутся, берете X = (L+R)/2. И проверяете, граф из первых X ребер является связным или нет. Если да, то R = X, иначе L = X и теперь вы знаете, что все ребра от 1 до X точно будут входить в ответ, это очевидно. Вот в этом месте нужно добавить их в граф и в следующие итерации считать, что они уже есть иначе у вас линейное время не получится.
UPD: Естественно X минимальных ребер надо искать за линейное время, а не сортировкой. Если вы затем сложите все операции, которые выполняются, то несложным образом получится линейное их число.
Вот у вас есть неотсортированный массив. Вы можете за линейное время переупорядочить ребра так, чтобы в левой половине все ребра были меньшие, чем в правой половине. Добавляете левую половину в граф. Проверяете на связность. Если несвязный, то добавляете всю левую половину в граф и забываете про нее навсегда. Считаете, что теперь весь ваш массив - это только правая половина.
Если связный, то просто навсегда забываете про правую половину(всё, что в ней хранится), но с графом ничего не делаете.
Ну вот зачем удалили условие?
"Условие задачи" - для Ctrl+F
Требуется построить алгоритм, находящий за линейное время (V+E) "минимальное" остовное дерево под "минимальное" подразумевется не сумма весов рёбер, а минимальность веса максимального веса среди рёбер этого дерева.