Алгоритм Куна-Мункреса
创建于:2024年12月29日
创建于:2024年12月29日
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
vector<int> w(n + 1);
for(int i = 1; i <= n; i++) {
cin >> w[i];
}
vector<vector<int>> c(n + 1, vector<int>(n + 1, 0));
for(int i = 1; i <= n; i++) {
int k;
cin >> k;
for(int j = 0; j < k; j++) {
int r;
cin >> r;
c[i][r] = w[i] * w[i];
}
}
int N = n;
vector<int> u(N + 1, 0), v(N + 1, 0), p(N + 1, 0), way(N + 1, 0);
for(int i = 1; i <= N; i++) {
p[0] = i;
int j0 = 0;
vector<int> minv(N + 1, 1e9);
vector<bool> used(N + 1, false);
do {
used[j0] = true;
int i1 = p[j0];
int delta = 1e9;
int j1 = 0;
for(int j = 1; j <= N; j++) {
if(!used[j]) {
int cur = -c[i1][j] - u[i1] - v[j];
if(cur < minv[j]) {
minv[j] = cur;
way[j] = j0;
}
if(minv[j] < delta) {
delta = minv[j];
j1 = j;
}
}
}
for(int j = 0; j <= N; j++) {
if(used[j]) {
u[p[j]] += delta;
v[j] -= delta;
}
else {
minv[j] -= delta;
}
}
j0 = j1;
} while(p[j0] != 0);
do {
int j1 = way[j0];
p[j0] = p[j1];
j0 = j1;
} while(j0 != 0);
}
vector<int> res(n + 1, 0);
for(int j = 1; j <= n; j++) {
if(p[j] != 0 && c[p[j]][j] > 0) {
res[p[j]] = j;
}
}
for(int i = 1; i <= n; i++) {
cout << res[i] << ' ';
}
}
что за алгоритм тут написан
Этот код реализует алгоритм Куна-Мункреса (также известный как алгоритм Венгерского метода) для нахождения максимального взвешенного паросочетания в двудольном графе. Давайте разберём основные компоненты и шаги этого алгоритма, представленного в коде:
Ввод данных:
n
— количество вершин в каждой из двух долей двудольного графа.w
— веса, связанные с вершинами одной из долей.c
— матрица стоимостей (в данном случае, квадраты весов w[i]^2
), где c[i][j]
представляет стоимость сопоставления вершины i
из одной доли с вершиной j
из другой доли. Если сопоставление невозможно, стоимость остаётся равной 0.Алгоритм Куна-Мункреса:
u
и v
представляют потенциалы для вершин обеих долей, которые используются для оптимизации поиска улучшений в паросочетании.i
из первой доли пытаемся найти соответствующую вершину j
из второй доли с максимальной суммой весов.minv
, used
, way
) для отслеживания минимальных затрат и путей улучшения текущего паросочетания.Формирование результата:
res
, который содержит сопоставления вершин из первой доли со второй.u
и v
) позволяет алгоритму эффективно корректировать стоимость сопоставлений и находить оптимальные пути улучшения.Таким образом, данный код реализует алгоритм Куна-Мункреса для поиска максимального взвешенного паросочетания в двудольном графе.
Дополнительные ресурсы для изучения:
Пример использования: Если у вас есть двудольный граф с весами на рёбрах, этот алгоритм поможет найти такое сопоставление вершин, при котором сумма весов выбранных рёбер будет максимальной.
Примечание: В коде используется матрица c[i][j] = w[i] * w[i]
, что подразумевает, что вес сопоставления зависит только от одной из вершин. В общем случае веса могут зависеть от обеих вершин.
Если у вас возникнут дополнительные вопросы по реализации или работе алгоритма, не стесняйтесь задавать!