Bài toán tìm cặp ghép cực đại
#include <bits/stdc++.h>
using namespace std;
#define MAX_NUT 114514
#define MAX_CANH 1919810
long long so_nut_A, so_nut_B, so_canh;
long long danh_dau[501], ket_noi[MAX_NUT], ket_qua;
typedef pair<long long, long long> Cap;
map<Cap, bool> canh_ton_tai;
bool tim_ket_noi(long long nut) {
for (int i = 1; i <= so_nut_B; ++i) {
if (danh_dau[i] || !canh_ton_tai[make_pair(nut, i)]) continue;
danh_dau[i] = 1;
if (!ket_noi[i] || tim_ket_noi(ket_noi[i])) {
ket_noi[i] = nut;
return true;
}
}
return false;
}
int main() {
cin >> so_nut_A >> so_nut_B >> so_canh;
for (int i = 0; i < so_canh; ++i) {
long long a, b;
cin >> a >> b;
if (canh_ton_tai[make_pair(a, b)]) continue;
canh_ton_tai[make_pair(a, b)] = true;
}
for (int i = 1; i <= so_nut_A; ++i) {
memset(danh_dau, 0, sizeof(danh_dau));
if (tim_ket_noi(i)) ket_qua++;
}
cout << ket_qua;
return 0;
}
Bài toán phủ đỉnh cực tiểu (Bài P7368)
#include <bits/stdc++.h>
using namespace std;
long long n, k;
long long danh_dau[501], ket_noi[MAX_NUT], ket_qua;
map<pair<long long, long long>, bool> canh_ton_tai;
bool tim_ket_noi(long long nut) {
for (int i = 1; i <= n; ++i) {
if (danh_dau[i] || !canh_ton_tai[make_pair(nut, i)]) continue;
danh_dau[i] = 1;
if (!ket_noi[i] || tim_ket_noi(ket_noi[i])) {
ket_noi[i] = nut;
return true;
}
}
return false;
}
int main() {
cin >> n >> k;
for (int i = 0; i < k; ++i) {
long long a, b;
cin >> a >> b;
canh_ton_tai[make_pair(a, b)] = true;
}
for (int i = 1; i <= n; ++i) {
memset(danh_dau, 0, sizeof(danh_dau));
if (tim_ket_noi(i)) ket_qua++;
}
cout << ket_qua;
return 0;
}
Thuật toán KM cho cặp ghép trọng số cực đại (Bài P1559)
#include <bits/stdc++.h>
using namespace std;
#define MAX_N 105
#define INF 1e9+7
long long n;
long long do_uu_tien[MAX_N][MAX_N], do_uu_tien_nho[MAX_N][MAX_N];
long long danh_dau_x[MAX_N], danh_dau_y[MAX_N], ket_noi[MAX_N], ket_qua;
long long gan_x[MAX_N], gan_y[MAX_N], khoang_cach[MAX_N];
bool tim_ket_noi(long long u) {
danh_dau_x[u] = 1;
for(int v = 1; v <= n; ++v) {
if(danh_dau_y[v]) continue;
long long t = gan_x[u] + gan_y[v] - do_uu_tien[u][v];
if(t == 0) {
danh_dau_y[v] = 1;
if(!ket_noi[v] || tim_ket_noi(ket_noi[v])) {
ket_noi[v] = u;
return true;
}
} else {
khoang_cach[v] = min(khoang_cach[v], t);
}
}
return false;
}
void giai_quyet() {
memset(ket_noi, 0, sizeof(ket_noi));
memset(gan_x, 0, sizeof(gan_x));
memset(gan_y, 0, sizeof(gan_y));
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
gan_x[i] = max(gan_x[i], do_uu_tien[i][j]);
for(int i = 1; i <= n; ++i) {
while(true) {
memset(danh_dau_x, 0, sizeof(danh_dau_x));
memset(danh_dau_y, 0, sizeof(danh_dau_y));
fill(khoang_cach, khoang_cach + MAX_N, INF);
if(tim_ket_noi(i)) break;
long long minn = INF;
for(int j = 1; j <= n; ++j)
if(!danh_dau_y[j]) minn = min(minn, khoang_cach[j]);
for(int j = 1; j <= n; ++j) {
if(danh_dau_x[j]) gan_x[j] -= minn;
if(danh_dau_y[j]) gan_y[j] += minn;
}
}
}
long long tong = 0;
for(int i = 1; i <= n; ++i) {
tong += gan_x[i];
if(ket_noi[i]) tong += gan_y[i];
}
cout << abs(tong);
}
int main() {
cin >> n;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
cin >> do_uu_tien[i][j];
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
cin >> do_uu_tien_nho[i][j];
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
do_uu_tien[i][j] = do_uu_tien[i][j] * do_uu_tien_nho[j][i];
giai_quyet();
return 0;
}