1

Тема: Обхід графа з обмеженнями

Дано граф у форматі початкова вершина, кінцева вершина, вартість переходу.
Початок і кінець маршруту.
А також кількість зупинок, які можна зробити при переході
з початку до кінця вказаного маршруту.
Потрібно знайти найдешевший шлях з пункту А в пункт Б із обмеженою кількістю зупинок.
Моделюється найдешевший переліт літаком з обмеженою кількістю пересадок.
Завдання звідси https://leetcode.com/problems/cheapest- … scription/ .

Найдешевший маршрут я знаходжу ось так:

class Solution {
public:
    int findCheapestPrice(const int& n, const vector<vector<int>>& flights, const int& src, const int& dst, const int& k)
    {
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> dist_vert;
        vector<int> distances(n, 1e9 + 7);
        distances[src] = 0;
        dist_vert.push(make_pair(0, src));

        while (!dist_vert.empty()) {
            pair<int, int> item = dist_vert.top();
            int distance = item.first;
            int vertex = item.second;
            dist_vert.pop();
            for (size_t i = 0; i < flights.size(); ++i) {
                int source = flights[i][0];
                int destin = flights[i][1];
                int price = flights[i][2];
                if (source == vertex && (distance + price < distances[destin])) {
                    distances[destin] = distance + price;
                    dist_vert.push(make_pair(distances[destin], destin));
                }
            }
        }

        return distances[dst] >= 1e9 + 7 ? -1 : distances[dst];
    }
};

Але не розумію як реалізувати обмеження зупинок.
Має бути якийсь бектрекінґ абощо, проте фантазії на нього бракує.

2

Re: Обхід графа з обмеженнями

Ось так переписав. Код працює, але жере забагато пам'яті.

class Solution {
    bool visited(const int& vertex, const vector<int>& path)
    {
        for (size_t i = 0; i < path.size(); ++i) {
            if (path[i] == vertex) {
                return true;
            }
        }
        return false;
    }

public:
    int findCheapestPrice(const int& n, const vector<vector<int>>& flights, const int& src, const int& dst, const int& k)
    {
        queue<vector<int>> paths;
        vector<int> path;
        path.push_back(src);
        paths.push(path);
        vector<vector<int>> total_paths;
        int answer { INT_MAX };

        while (!paths.empty()) {
            path = paths.front();
            paths.pop();
            int last = path[path.size() - 1];
            if (last == dst) {
                int path_size = path.size();
                if (path_size <= k + 2) {

                    total_paths.push_back(path);
                }
            }
            for (size_t i = 0; i < flights.size(); ++i) {
                int source = flights[i][0];
                int target = flights[i][1];
                if (source == last && !visited(target, path)) {
                    vector<int> new_path(path);
                    new_path.push_back(target);
                    paths.push(new_path);
                }
            }
        }
        for (size_t i = 0; i < total_paths.size(); ++i) {
            int cur_path { 0 };
            for (size_t j = 0; j < total_paths[i].size() - 1; ++j) {
                for (size_t f = 0; f < flights.size(); ++f) {
                    if (flights[f][0] == total_paths[i][j] && flights[f][1] == total_paths[i][j + 1]) {
                        cur_path += flights[f][2];
                    }
                }
            }
            answer = min(cur_path, answer);
        }
        return total_paths.empty() ? -1 : answer;
    }
};

3

Re: Обхід графа з обмеженнями

Привiт Tag Miles. Вирiшив таки порушити тишу. Скажiть будь ласка, чи ви самi написали ваш код?

4

Re: Обхід графа з обмеженнями

steamwater написав:

Привiт Tag Miles. Вирiшив таки порушити тишу. Скажiть будь ласка, чи ви самi написали ваш код?

Якщо не працює нормально, точно сам написав:). Давно вже списав рішення для цієї задачі і забув про нього:).

Подякували: steamwater1

5 Востаннє редагувалося steamwater (27.01.2025 19:08:04)

Re: Обхід графа з обмеженнями

Teg Miles написав:

Якщо не працює нормально, точно сам написав:). Давно вже списав рішення для цієї задачі і забув про нього:).

Навпаки. Я по iнтернет замучався шукати та так i не знайшов жодного працюючого прикладу. А ваш, - працює. Не швидко, що правда. I ще, - вiн падає на кiлькостях мiст-лiтовищ що перевищують 25, якщо середня кiлькiсть рейсiв перевищує 70-80. Але працює! Враховуючи, що це не самий простий алгоритм. мушу сказати, що ваш рiвень зростає. Якщо бажаєте подивитися на мiй то вiн отут:
https://github.com/IgorPolozov/leetcode … ersing.cpp
доволi швидкий та витривалий до великих обсягiв графу.
Доречi, чи припускає leetcode якiйсь фiдбек. Тобто, чи можуть юзери надсилати рiшення до них?
I ще. Ви кажете - списали рiшення. Тобто ви знайшли у тенетах щось, що таки працює? Якщо так, - покидайте посиланнь, будь ласка.

6

Re: Обхід графа з обмеженнями

steamwater написав:
Teg Miles написав:

Якщо не працює нормально, точно сам написав:). Давно вже списав рішення для цієї задачі і забув про нього:).

Навпаки. Я по iнтернет замучався шукати та так i не знайшов жодного працюючого прикладу. А ваш, - працює. Не швидко, що правда. I ще, - вiн падає на кiлькостях мiст-лiтовищ що перевищують 25, якщо середня кiлькiсть рейсiв перевищує 70-80. Але працює! Враховуючи, що це не самий простий алгоритм. мушу сказати, що ваш рiвень зростає. Якщо бажаєте подивитися на мiй то вiн отут:
https://github.com/IgorPolozov/leetcode … ersing.cpp
доволi швидкий та витривалий до великих обсягiв графу.
Доречi, чи припускає leetcode якiйсь фiдбек. Тобто, чи можуть юзери надсилати рiшення до них?
I ще. Ви кажете - списали рiшення. Тобто ви знайшли у тенетах щось, що таки працює? Якщо так, - покидайте посиланнь, будь ласка.

Ось моє чесно списане рішення:

class Solution {
public:
    int findCheapestPrice(const int& n, const vector<vector<int>>& flights, const int& src, const int& dst, const int& k)
    {
        vector<vector<pair<int, int>>> graph(n);
        for (const auto& item : flights) {
            graph[item[0]].push_back({ item[1], item[2] });
        }
        priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> vertexes;
        vertexes.push({ 0, src, 0 });
        vector<int> dist(n + 1, INT_MAX);

        while (!vertexes.empty()) {
            auto item = vertexes.top();
            vertexes.pop();
            int price = item[0];
            int vertex = item[1];
            int end = item[2];

            if (vertex == dst) {
                return price;
            }
            if (dist[vertex] < end) {
                continue;
            }
            dist[vertex] = end;

            if (end > k) {
                continue;
            }
            for (const auto& next_vertex : graph[vertex]) {
                vertexes.push({ price + next_vertex.second, next_vertex.first, end + 1 });
            }
        }
        return -1;
    }
};

На LeetCode в кожному завданні є категорія Solutions, там готові рішення від різних користувачів.
Якщо я взагалі не уявляю як вирішити завдання, просто списую, намагаючись запам'ятати підхід та його деталі.
Коли маю якесь рішення, але воно не працює як слід, запитую тут.
Ваше рішення мені дуже важко зрозуміти.

7 Востаннє редагувалося steamwater (27.01.2025 19:57:29)

Re: Обхід графа з обмеженнями

Teg Miles написав:

Ваше рішення мені дуже важко зрозуміти.

  Там є readme: https://github.com/IgorPolozov/leetcod … README.md
та коментарi у кодi. На питання по конкретних мiсцях, вiдповiм. За чесно списане рiшення дякую, - завтра потестю. I на leetcode'i подивлюсь. А чи можна своє їм якось запхнути? Я, чесно кажучи аж цiлий фрейм-ворк накатав, щоб генерити випадковi вектори польотiв. Та цiкаво чи вони тестять (на серваку).

8

Re: Обхід графа з обмеженнями

steamwater написав:
Teg Miles написав:

Ваше рішення мені дуже важко зрозуміти.

  Там є readme: https://github.com/IgorPolozov/leetcod … README.md
та коментарi у кодi. На питання по конкретних мiсцях, вiдповiм. За чесно списане рiшення дякую, - завтра потестю. I на leetcode'i подивлюсь. А чи можна своє їм якось запхнути? Я, чесно кажучи аж цiлий фрейм-ворк накатав, щоб генерити випадковi вектори польотiв. Та цiкаво чи вони тестять (на серваку).

Можна. Коли ви вирішуєте завдання, якщо ваше рішення прийняте,
то в категорії Solutions з'являється можливість додати своє рішення.
Там купи різних рішень, найбільше цінуються компактні та швидкі (за швидкістю виконання).
Якщо ваше рішення матиме менше 100% швидкості,
то, швидше за все, загубиться серед решти.

9

Re: Обхід графа з обмеженнями

Я бачу що там на деякi речи треба сплачувати пiдписку 35$/мiсяць. То як здати на перевiрку?

10

Re: Обхід графа з обмеженнями

steamwater написав:

Я бачу що там на деякi речи треба сплачувати пiдписку 35$/мiсяць. То як здати на перевiрку?

Зайдіть у необхідне завдання, вставте своє рішення у віконце для рішень і запустіть його.
Якщо рішення прийняте, далі в розділ Solutions, там згори з'явиться запрошення додати своє рішення.
Наскільки я знаю, додавання своїх рішень безкоштовне.

Подякували: steamwater, leofun012

11 Востаннє редагувалося steamwater (27.01.2025 21:40:34)

Re: Обхід графа з обмеженнями

Я ж кажу, що на leetcode тупi хлопцi. Чи може я щось не те роблю. Я зарегався, одержав на мило повiдомлення та пройшов за посиланням. Сплило вiконце - email confirmation compleety. А коли став намагатись комiтити код чи прогрнати його на виконання, що те що те знов вимагають перевiрки поштової адреси. Така ж iсторiя була гiтхабi поки я на поскаржився, що було не просто. Не вважили таку адресу дiйсною. Тепер на leetcod така ж дурня. Але зараз я пiдтверджую вiрнiсть адреси i вони кажуть, що вона є але epired(?), та просять ввести ще одну... Ну от чому могуть навчити люди в я ких руки не з плiч i не з дупи, а десь посерединi. :D

12

Re: Обхід графа з обмеженнями

Перезайшов на сайт з нуля i все спрацювало. I цi люди розповiдають навачкам про iнiцiалiзацiю! Не знаю гарно воно чи погано, але прийняте:https://leetcode.com/problems/cheapest- … 522532439/

13 Востаннє редагувалося steamwater (27.01.2025 22:31:14)

Re: Обхід графа з обмеженнями

steamwater написав:

Перезайшов на сайт з нуля i все спрацювало. I цi люди розповiдають навачкам про iнiцiалiзацiю! Не знаю гарно воно чи погано, але прийняте:https://leetcode.com/problems/cheapest- … 522532439/

Що таке beats? Як я розумiю воно вiдноситься до перфомансу. То чим бiльше тим краще, чи навпаки?

14 Востаннє редагувалося Teg Miles (27.01.2025 22:54:39)

Re: Обхід графа з обмеженнями

steamwater написав:
steamwater написав:

Перезайшов на сайт з нуля i все спрацювало. I цi люди розповiдають навачкам про iнiцiалiзацiю! Не знаю гарно воно чи погано, але прийняте:https://leetcode.com/problems/cheapest- … 522532439/

Що таке beats? Як я розумiю воно вiдноситься до перфомансу. То чим бiльше тим краще, чи навпаки?

Так, чим більше, тим краще. В ідеалі по 100% має бути.
Порівнюється швидкість і використання пам'яті з іншими рішеннями.

Подякували: leofun011

15

Re: Обхід графа з обмеженнями

Teg Miles написав:
steamwater написав:
steamwater написав:

Перезайшов на сайт з нуля i все спрацювало. I цi люди розповiдають навачкам про iнiцiалiзацiю! Не знаю гарно воно чи погано, але прийняте:https://leetcode.com/problems/cheapest- … 522532439/

Що таке beats? Як я розумiю воно вiдноситься до перфомансу. То чим бiльше тим краще, чи навпаки?

Так, чим більше, тим краще. В ідеалі по 100% має бути.
Порівнюється швидкість і використання пам'яті з іншими рішеннями.

Тодi моє десь у хвостi. Треба буде подивитися на тi що краще. Я знаю як моє можно покращити теж, але не певен наскiльки. I ще одне неподобство. Вони самi задали предефайнед структури даних, що немає сенсу. Тобто я у цiй незгабнiй функцiї їх пишу заново. Виходить багато коду. А їх аналiзатор складностi вiдмовляє у аналiзi бо коду багато. Але нехай. Цiкаво подивитися як вигляда код що аж вдесятеро швидший.

16 Востаннє редагувалося steamwater (28.01.2025 12:30:03)

Re: Обхід графа з обмеженнями

День почався з розчарування. От код з сайту: https://leetcode.com/problems/cheapest- … n-tle-now/
я розкрив бiндiнг iнiти, щоб С++11 був здатен компiлити:

#include<tuple>
typedef std::tuple<int,int,int> ti;
class Solution{
public:
    int findCheapestPrice(int n, std::vector<std::vector<int>>& flights, int src, int dst, int K) {
        std::vector<std::vector<std::pair<int,int>>>vp(n);
        for(const auto&f:flights)   vp[f[0]].emplace_back(f[1],f[2]);
        std::priority_queue<ti,std::vector<ti>,std::greater<ti>>pq;
        pq.emplace(0,src,K+1);
        while(!pq.empty()){
           // auto [cost,u,stops] = pq.top();//replaced for C++11 as
            auto cost=std::get<0, int>(pq.top());
            auto u=std::get<1, int>(pq.top());
            auto stops=std::get<2, int>(pq.top());

            pq.pop();
            if(u==dst)  return cost;
            if(!stops)  continue;
            for(auto to:vp[u]){
                //auto [v,w] = to;//replaced for C++11 as
                auto v=std::get<0, int>(to);
                auto w=std::get<1, int>(to);
                pq.emplace(cost+w,v,stops-1);
            }
        }
        return -1;
    }
};

i воно падає у найпростiшому тестi... Код порушення доступу до захищеної пам'ятi. I це найперший код з роздiлу leetcode/Solutions/C++
test case:

int flights_number=4, start=1, finish=5, stops_max=2;
using vec_int=std::vector;
using vec_source = std::vector<vec_int>;
vec_source flights=
{//from, to, price
{1, 2, 100 }, {1, 3, 200}, {1, 5, 5}, {2, 3, 5},
{2, 5, 50}, {2, 6, 30}, {3, 5, 2}, {5, 6, 10}, {5, 1, 1000}
};
//the sample of call:
int res=Solution{}.findCheapestPrice(flights_number, flights, start, finish, stops_max);

17

Re: Обхід графа з обмеженнями

Нащо ви це робите, можете пояснити?
Тобто помилка очевидна, але видно, що ваш рівень дещо не дістає, щоб її побачити; але в такому разі нащо вам відносно складний алгоритм, коли вам основи треба вчити?
Можете сказати, який тип змінної cost? Підказка: НЕ int.

Подякували: steamwater, leofun012

18 Востаннє редагувалося steamwater (28.01.2025 13:39:23)

Re: Обхід графа з обмеженнями

koala написав:

Нащо ви це робите, можете пояснити?
Тобто помилка очевидна, але видно, що ваш рівень дещо не дістає, щоб її побачити; але в такому разі нащо вам відносно складний алгоритм, коли вам основи треба вчити?
Можете сказати, який тип змінної cost? Підказка: НЕ int.

Не вiдповiднiсть типiв встановлюється на стадiї компiляцiї. Тобто в вас воно працює?
Доречи, лiнива це ледаща чи шо?

19

Re: Обхід графа з обмеженнями

steamwater написав:

Не вiдповiднiсть типiв встановлюється на стадiї компiляцiї.

Якщо немає неявного перетворення.

steamwater написав:

Доречи, лiнива це ледаща чи шо?

А ви мене переледачили. Навіть не намагалися словник відкрити, так?

20 Востаннє редагувалося steamwater (28.01.2025 14:55:29)

Re: Обхід графа з обмеженнями

Так. Не знав такого слова. Але чому вас дратує порушення тишi у роздiлi? Я можу помилятись вiдносно   priority_queue, але на мiй розсуд у кодi задекларовано чергу що складається з елементiв- туплiв i внутрiшньо це обгорнутий вектор туплiв. Елементи сортуються згiдно до предiкату що порiвнюватиме  тупли - value_type елементи. Це означа, що top() поверта посилання на тупл iнтiв. Тоди get<0> та iншi мають повертати посилання на елементи тупла. Дабл реф схлопується (decays) до просто, реф... У кодi використано auto, ба не auto & (до речi й цей варiант не працює, хоч вiн тут не потрiбен, я вважаю). То ж не лiнуйтеся, а пояснiть свою думку докладнiше. I якщо ваша ласка, то покажiть як би ви транслювали той 17 код на 11.