মিন-কস্ট-ফ্লো ব্যবহার করে অ্যাসাইনমেন্ট প্রবলেম সমাধান#
অ্যাসাইনমেন্ট প্রবলেমের দুটি সমতুল্য বিবৃতি আছে:
- একটি বর্গ ম্যাট্রিক্স $A[1..N, 1..N]$ দেওয়া আছে, এতে $N$ টি উপাদান নির্বাচন করতে হবে যেন প্রতিটি সারি ও কলামে ঠিক একটি উপাদান নির্বাচিত হয় এবং এই উপাদানগুলোর মানের যোগফল সর্বনিম্ন হয়।
- $N$ টি অর্ডার এবং $N$ টি মেশিন আছে। প্রতিটি অর্ডারের জন্য প্রতিটি মেশিনে তৈরির খরচ জানা আছে। প্রতিটি মেশিনে শুধুমাত্র একটি অর্ডার সম্পাদন করা যায়। সকল অর্ডার মেশিনগুলোতে এমনভাবে অ্যাসাইন করতে হবে যেন মোট খরচ সর্বনিম্ন হয়।
এখানে আমরা মিনিমাম কস্ট ফ্লো (মিন-কস্ট-ফ্লো) নির্ণয়ের অ্যালগরিদমের উপর ভিত্তি করে সমস্যার সমাধান বিবেচনা করব, যা $\mathcal{O}(N^3)$ সময়ে অ্যাসাইনমেন্ট প্রবলেম সমাধান করে।
বর্ণনা#
আসুন একটি বাইপার্টাইট নেটওয়ার্ক তৈরি করি: একটি সোর্স $S$, একটি সিংক $T$, প্রথম অংশে $N$ টি ভার্টেক্স (ম্যাট্রিক্সের সারি বা অর্ডারের সাথে সঙ্গতিপূর্ণ), দ্বিতীয় অংশেও $N$ টি ভার্টেক্স (ম্যাট্রিক্সের কলাম বা মেশিনের সাথে সঙ্গতিপূর্ণ)। প্রথম সেটের প্রতিটি ভার্টেক্স $i$ এবং দ্বিতীয় সেটের প্রতিটি ভার্টেক্স $j$-এর মধ্যে ব্যান্ডউইথ ১ এবং কস্ট $A_{ij}$ সহ একটি এজ আঁকি। সোর্স $S$ থেকে প্রথম সেটের সকল ভার্টেক্স $i$-তে ব্যান্ডউইথ ১ এবং কস্ট ০ সহ এজ আঁকি। দ্বিতীয় সেটের প্রতিটি ভার্টেক্স $j$ থেকে সিংক $T$-তে ব্যান্ডউইথ ১ এবং কস্ট ০ সহ একটি এজ আঁকি।
প্রাপ্ত নেটওয়ার্কে মিনিমাম কস্টের ম্যাক্সিমাম ফ্লো খুঁজি। স্পষ্টতই, ফ্লো-এর মান $N$ হবে। এছাড়াও, প্রথম সেগমেন্টের প্রতিটি ভার্টেক্স $i$-এর জন্য দ্বিতীয় সেগমেন্টের ঠিক একটি ভার্টেক্স $j$ আছে, যেখানে ফ্লো $F_{ij}$ = ১। পরিশেষে, এটি প্রথম সেগমেন্ট ও দ্বিতীয় অংশের ভার্টেক্সগুলোর মধ্যে একটি এক-এক সঙ্গতি, যা সমস্যার সমাধান (যেহেতু প্রাপ্ত ফ্লো-এর কস্ট সর্বনিম্ন, তাই নির্বাচিত এজগুলোর কস্টের যোগফল সম্ভাব্য সর্বনিম্ন হবে, যা অপটিমালিটির মানদণ্ড)।
এই সমাধানের কমপ্লেক্সিটি নির্ভর করে মিনিমাম কস্টের ম্যাক্সিমাম ফ্লো খোঁজার জন্য কোন অ্যালগরিদম ব্যবহৃত হচ্ছে তার উপর। ডায়াক্সট্রা ব্যবহার করলে কমপ্লেক্সিটি হবে $\mathcal{O}(N^3)$ অথবা বেলম্যান-ফোর্ড ব্যবহার করলে $\mathcal{O}(N^4)$। এর কারণ হলো ফ্লো-এর আকার $O(N)$ এবং ডায়াক্সট্রা অ্যালগরিদমের প্রতিটি ইটারেশন $O(N^2)$ সময়ে সম্পন্ন করা যায়, যেখানে বেলম্যান-ফোর্ডের জন্য এটি $O(N^3)$।
ইমপ্লিমেন্টেশন#
এখানে দেওয়া ইমপ্লিমেন্টেশনটি দীর্ঘ, এটি সম্ভবত উল্লেখযোগ্যভাবে সংক্ষিপ্ত করা যায়। এটি শর্টেস্ট পাথ নির্ণয়ের জন্য SPFA অ্যালগরিদম ব্যবহার করে।
const int INF = 1000 * 1000 * 1000;
vector<int> assignment(vector<vector<int>> a) {
int n = a.size();
int m = n * 2 + 2;
vector<vector<int>> f(m, vector<int>(m));
int s = m - 2, t = m - 1;
int cost = 0;
while (true) {
vector<int> dist(m, INF);
vector<int> p(m);
vector<bool> inq(m, false);
queue<int> q;
dist[s] = 0;
p[s] = -1;
q.push(s);
while (!q.empty()) {
int v = q.front();
q.pop();
inq[v] = false;
if (v == s) {
for (int i = 0; i < n; ++i) {
if (f[s][i] == 0) {
dist[i] = 0;
p[i] = s;
inq[i] = true;
q.push(i);
}
}
} else {
if (v < n) {
for (int j = n; j < n + n; ++j) {
if (f[v][j] < 1 && dist[j] > dist[v] + a[v][j - n]) {
dist[j] = dist[v] + a[v][j - n];
p[j] = v;
if (!inq[j]) {
q.push(j);
inq[j] = true;
}
}
}
} else {
for (int j = 0; j < n; ++j) {
if (f[v][j] < 0 && dist[j] > dist[v] - a[j][v - n]) {
dist[j] = dist[v] - a[j][v - n];
p[j] = v;
if (!inq[j]) {
q.push(j);
inq[j] = true;
}
}
}
}
}
}
int curcost = INF;
for (int i = n; i < n + n; ++i) {
if (f[i][t] == 0 && dist[i] < curcost) {
curcost = dist[i];
p[t] = i;
}
}
if (curcost == INF)
break;
cost += curcost;
for (int cur = t; cur != -1; cur = p[cur]) {
int prev = p[cur];
if (prev != -1)
f[cur][prev] = -(f[prev][cur] = 1);
}
}
vector<int> answer(n);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (f[i][j + n] == 1)
answer[i] = j;
}
}
return answer;
}