帶權二分圖板子-km(n^3)時間

#include <bits/stdc++.h>
#define mset(a, x) memset(a, x, sizeof(a))
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int N = 305;//n爲容量
int n;
int mp[N][N];//往這裏面存值第一個是左邊編號第二個右邊編號值爲權值
int match[N];
int exright[N], exleft[N];
int visright[N], visleft[N];
int slack[N];
int dfs(int left) {
    visleft[left] = 1;
    for (int i = 0; i < n; i++) {
        if (visright[i]) continue;
        int tmp = exleft[left] + exright[i] - mp[left][i];
        if (tmp == 0) {
            visright[i] = 1;
            if (match[i] == -1 || dfs(match[i])) {
                match[i] = left;
                return 1;
            }
        } else {
            slack[i] = min(slack[i], tmp);
        }
    }
    return 0;
}
int km() {
    mset(match, -1); mset(exright, 0);
    for (int i = 0; i < n; i++) {
        exleft[i] = mp[i][0];
        for (int j = 1; j < n; j++) {
            exleft[i] = max(exleft[i], mp[i][j]);
        }
    }
    for (int i = 0; i < n; i++) {
        mset(slack, INF);
        while (1) {
            mset(visright, 0); mset(visleft, 0);
            if (dfs(i)) {
                break;
            }
            int d = INF;
            for (int j = 0; j < n; j++) {
                if (!visright[j]) {
                    d = min(d, slack[j]);
                }
            }
            for (int j = 0; j < n; j++) {
                if (visleft[j]) {
                    exleft[j] -= d;
                }
                if (visright[j]) {
                    exright[j] += d;
                } else {
                    slack[j] -= d;
                }
            }
        }
    }
    int res = 0;
    for (int i = 0; i < n; i++) {
        res += mp[match[i]][i];
    }
    return res;
}
int main() {
    //用時往mp數組裏面加值調用即可
    int ans = km();//ans爲答案

    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章