কম্পিউটার টিউটোরিয়াল

C++-এ প্রথম শহর থেকে যেকোনো শহরে পৌঁছানোর জন্য ন্যূনতম সড়ক নির্মাণ প্রোগ্রাম


মান लीजिए हमारे पास costs_from এবং costs_to নামে একই আকারের দুটি তালিকা রয়েছে, যেখানে প্রতিটি সূচক i একটি শহরকে প্রতিনিধিত্ব করে। শহর i থেকে শহর j পর্যন্ত একমুখী সড়ক তৈরির খরচ হবে costs_from[i] + costs_to[j]। আমাদের কাছে একটি এজ লিস্টও আছে যেখানে প্রতিটি এজ [x, y] নির্দেশ করে যে শহর x থেকে শহর y পর্যন্ত ইতিমধ্যে একটি একমুখী সড়ক রয়েছে। যদি আমরা শহর ০ থেকে যেকোনো শহরে যেতে চাই, তবে প্রয়োজনীয় সড়কগুলো নির্মাণের ন্যূনতম খরচ বের করতে হবে।

উদাহরণ

ইনপুট: costs_from = [6, 2, 2, 12], costs_to = [2, 2, 3, 2], edges = [[0, 3]]

আউটপুট: 13

ব্যাখ্যা: আমরা ০ থেকে ২ নম্বর শহরে যেতে পারি ৯ খরচে (৬+৩)। তারপর ২ থেকে ১ নম্বর শহরে যেতে পারি ৪ খরচে (২+২)। এবং ০ থেকে ৩ নম্বর শহরে যাওয়ার সড়ক ইতিমধ্যে আছে। মোট খরচ = ৯ + ৪ = ১৩।

সমাধানের ধাপসমূহ

  1. n := costs_from এর আকার
  2. ret := 0
  3. দুটি ম্যাপ সংজ্ঞায়িত করুন: edges এবং redges
  4. প্রতিটি it এজের জন্য g-তে:
    • edges[it[0]]-এ it[1] যোগ করুন
    • redges[it[1]]-এ it[0] যোগ করুন
  5. from_cost := infinity
  6. দুটি সেট সংজ্ঞায়িত করুন: visited এবং reachable
  7. dfs(i) ফাংশন সংজ্ঞায়িত করুন:
    • যদি i ভিজিট না করা হয় এবং reachable-এ না থাকে:
      • i-কে visited-এ যোগ করুন
      • প্রতিটি j edges[i]-তে: dfs(j) কল করুন
      • i-কে po অ্যারেতে যোগ করুন
  8. dfs2(i) ফাংশন সংজ্ঞায়িত করুন:
    • যদি i ভিজিট করা হয়: true ফেরত দিন
    • যদি i reachable-এ থাকে: false ফেরত দিন
    • i-কে ভিজিট এবং reachable হিসেবে চিহ্নিত করুন
    • ret := true
    • প্রতিটি j redges[i]-তে: ret := ret AND dfs2(j)
    • ret ফেরত দিন
  9. একটি কিউ q সংজ্ঞায়িত করুন
  10. 0-কে reachable এবং q-এ যোগ করুন
  11. যখন q খালি না হয়:
    • node := q-র প্রথম উপাদান
    • q-র থেকে উপাদান মুছুন
    • প্রতিটি i edges[node]-তে:
      • যদি i reachable-এ না থাকে: i-কে reachable এবং q-এ যোগ করুন
    • from_cost := min(from_cost, costs_from[node])
  12. global_min := costs_from-এর ন্যূনতম উপাদান
  13. ret := ret + from_cost - global_min
  14. একটি অ্যারে po সংজ্ঞায়িত করুন
  15. i = 0 থেকে n পর্যন্ত: dfs(i) কল করুন
  16. po অ্যারে উল্টে দিন
  17. প্রতিটি i po-তে:
    • যদি i reachable-এ থাকে: পরবর্তী ইটেরেশনে যান
    • visited অ্যারে ক্লিয়ার করুন
    • initial := dfs2(i)
    • যদি initial সত্য হয়:
      • best := infinity
      • প্রতিটি j visited-তে: best := min(best, costs_to[j])
      • ret := ret + global_min + best
  18. ret ফেরত দিন

C++ বাস্তবায়ন

#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    int solve(vector<int>& costs_from, vector<int>& costs_to, vector<vector<int>>& g) {
        int n = costs_from.size();
        int ret = 0;
        map<int, vector<int>> edges;
        map<int, vector<int>> redges;
        for (auto& it : g) {
            edges[it[0]].push_back(it[1]);
            redges[it[1]].push_back(it[0]);
        }
        int from_cost = INT_MAX;
        set<int> visited;
        set<int> reachable;
        queue<int> q;
        reachable.insert(0);
        q.push(0);
        while (!q.empty()) {
            int node = q.front();
            q.pop();
            for (int i : edges[node]) {
                if (!reachable.count(i)) {
                    reachable.insert(i);
                    q.push(i);
                }
            }
            from_cost = min(from_cost, costs_from[node]);
        }
        int global_min = *min_element(costs_from.begin(), costs_from.end());
        ret += from_cost - global_min;
        vector<int> po;
        function<void(int)> dfs;
        dfs = [&](int i) {
            if (!visited.count(i) && !reachable.count(i)) {
                visited.insert(i);
                for (int j : edges[i]) {
                    dfs(j);
                }
                po.push_back(i);
            }
        };
        for (int i = 0; i < n; i++) dfs(i);
        reverse(po.begin(), po.end());
        function<bool(int)> dfs2;
        dfs2 = [&](int i) {
            if (visited.count(i)) return true;
            if (reachable.count(i)) return false;
            visited.insert(i);
            reachable.insert(i);
            bool ret = true;
            for (int j : redges[i]) {
                ret &= dfs2(j);
            }
            return ret;
        };
        for (int i : po) {
            if (reachable.count(i)) continue;
            visited.clear();
            bool initial = dfs2(i);
            if (initial) {
                int best = INT_MAX;
                for (int j : visited) {
                    best = min(best, costs_to[j]);
                }
                ret += global_min + best;
            }
        }
        return ret;
    }
};

int solve(vector<int>& costs_from, vector<int>& costs_to, vector<vector<int>>& edges) {
    return (new Solution())->solve(costs_from, costs_to, edges);
}

int main() {
    vector<int> costs_from = {6, 2, 2, 12};
    vector<int> costs_to = {2, 2, 3, 2};
    vector<vector<int>> edges = {{0, 3}};
    cout << solve(costs_from, costs_to, edges);
    return 0;
}

ইনপুট

{6, 2, 2, 12}, {2, 2, 3, 2}, {{0, 3}}

আউটপুট

13
  1. C++-এ প্রতিপক্ষকে ধরতে ন্যূনতম রাউন্ড সংখ্যা বের করা

  2. সি++ প্রোগ্রাম: গ্রাফকে ডিসকানেক্টেড করার জন্য ন্যূনতম এজ কাট (Minimum Edges to Cut) বের করা

  3. সি++ প্রোগ্রাম: যেকোনো বীজগাণিতিক অভিব্যক্তির ন্যূনতম মান (Minimum Value) বের করা

  4. পাইথনে একটি সংখ্যাকে অন্য সংখ্যায় রূপান্তর করার ন্যূনতম অপারেশন বের করার প্রোগ্রাম