中文题干,而且他数据都已经按照表的格式排列好了。。。
一道赤裸裸的KM题目吧。人买房子,花钱。
所以就用KM算法了。
我把之前O(
n
4
n^4
n4)的代码往上一敲,结果TLE了。
抱着试一下的心态,用了下scanf printf。过了= =。这算是运气?
int w[len][len], n;
int x[len], y[len];
int l[len], S[len],T[len];//常规的数组们。
int main(){
while (~scanf("%d", &n)) {
Init();
for (int i=1; i<=n; i++){
for (int j=1; j<=n; j++){
scanf("%d", &w[i][j]);
}
}
KM();
int ans = 0;
// for (int i=1; i<=n; i++) cout << x[i] << " ";
// for (int i=1; i<=n; i++) cout << y[i] << " ";
for (int i=1; i<=n; i++){
ans = ans + x[i];
ans = ans + y[i];
}//顶标值就是最佳匹配值了
printf("%d\n", ans);
}
return 0;
}
```cpp
void Init(){
memset(w, 0, sizeof(w));
memset(l, 0, sizeof(l));
memset(x, 0, sizeof(x));
memset(y, 0, sizeof(y));
memset(S, 0, sizeof(S));
memset(T, 0, sizeof(T));
}
void KM(){
for (int i=1; i<=n; i++){
l[i] = x[i] = y[i] = 0;
for (int j=1; j<=n; j++)
x[i] = max(x[i], w[i][j]);
}
for (int i=1; i<=n; i++){
while (true) {
memset(S, 0, sizeof(S));
memset(T, 0, sizeof(T));
if (find(i)) break;
else update();
}
}
}
//KM的两个部分 增广路和更新
bool find(int p){
S[p] ++;
for (int j=1; j<=n; j++){
if(x[p] + y[j] == w[p][j] && T[j] == 0){
T[j]++;
if (l[j] == 0 || find(l[j])){
l[j] = p;
return true;
}
}
}
return false;
}
void update(){
int a = 0x3f3f3f3f;
for (int i=1; i<=n; i++){
if (S[i] != 0){
for (int j=1; j<=n; j++){
if (T[j] == 0) a = min(a, x[i]+y[j]-w[i][j]);
}
}
}
for (int i=1; i<=n; i++){
if (S[i] != 0) x[i] = x[i] - a;
if (T[i] != 0) y[i] = y[i] + a;
}
}