#include <bits/stdc++.h>
#define mem(a, b) memset(a, b, sizeof a)
using namespace std;
const int N = 105;
int w[N][N];// 边权
int la[N], lb[N];// 左、右部点的顶标
bool va[N], vb[N];// 访问标记:是否在交错树中
int match[N];
int n, delta;
bool dfs(int x) {
va[x] = 1;// 访问标记:x在交错树中
for (int y = 1; y <= n; y++) {
if (!vb[y]) {
if (la[x] + lb[y] == w[x][y]) {// 是一个相等子图
vb[y] = 1;// 访问标记:y在交错树中
if (match[y] == -1 || dfs(match[y])) {
match[y] = x;
return true;
}
}
else delta = min(delta, la[x] + lb[y] - w[x][y]);
}
}
return false;
}
int km() {
for (int i = 1; i <= n; i++) {
la[i] = -(1 << 30);// -inf
lb[i] = 0;
for (int j = 1; j <= n; j++) {
la[i] = max(la[i], w[i][j]);
}
}
for (int i = 1; i <= n; i++) {
while (true) {
mem(va, false);
mem(vb, false);
delta = (1 << 30);// inf
if (dfs(i))break;
for (int j = 1; j <= n; j++) {
if (va[j])la[j] -= delta;
if (vb[j])lb[j] += delta;
}
}
}
int res = 0;
for (int i = 1; i <= n; i++)res += w[match[i]][i];
return res;
}
void add(int a, int b, int c) {
w[a][b] = c;
}
int main()
{
mem(match, -1);
n = 4;
add(1, 1, 5);
add(1, 3, 10);
add(2, 2, 5);
add(2, 4, 10);
add(3, 1, 10);
add(3, 3, 5);
add(4, 2, 10);
add(4, 4, 5);
cout << km();
return 0;
}
此种方法可以再优化