P6577 KM

题意

传送门 P6577 【模板】二分图最大权完美匹配

题解

KM 算法裸题。BFS 求增广路,总时间复杂度 O ( n 3 ) O(n^3) O(n3)

#include 
using namespace std;
#define pb push_back
typedef long long ll;
const int MAXN = 505;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int N, M;
int lmatch[MAXN], rmatch[MAXN], pre[MAXN];
ll G[MAXN][MAXN], lmark[MAXN], rmark[MAXN], slack[MAXN];
bool lused[MAXN], rused[MAXN];
queue<int> q;

bool check(int v)
{
    rused[v] = 1;
    if (rmatch[v] != -1)
    {
        int u = rmatch[v];
        if (!lused[u])
            lused[u] = 1, q.push(u);
        return 0;
    }
    while (v != -1)
        swap(v, lmatch[rmatch[v] = pre[v]]);
    return 1;
}

void bfs(int s)
{
    memset(lused, 0, sizeof(lused));
    memset(rused, 0, sizeof(rused));
    memset(slack, 0x3f, sizeof(slack));
    while (q.size())
        q.pop();
    lused[s] = 1, q.push(s);
    for (;;)
    {
        while (q.size())
        {
            int v = q.front();
            q.pop();
            for (int u = 0; u < N; ++u)
            {
                ll d = lmark[v] + rmark[u] - G[v][u];
                if (!rused[u] && d < slack[u])
                {
                    slack[u] = d, pre[u] = v;
                    if (!d && check(u))
                        return;
                }
            }
        }
        ll d = INF;
        for (int v = 0; v < N; ++v)
            if (!rused[v])
                d = min(d, slack[v]);
        for (int v = 0; v < N; ++v)
        {
            if (lused[v])
                lmark[v] -= d;
            if (rused[v])
                rmark[v] += d;
            else
                slack[v] -= d;
        }
        for (int v = 0; v < N; ++v)
            if (!rused[v] && !slack[v] && check(v))
                return;
    }
}

void KM()
{
    memset(lmark, 0xc0, sizeof(lmark));
    memset(rmark, 0, sizeof(rmark));
    memset(lmatch, -1, sizeof(lmatch));
    memset(rmatch, -1, sizeof(rmatch));
    for (int i = 0; i < N; ++i)
        for (int j = 0; j < N; ++j)
            lmark[i] = max(lmark[i], G[i][j]);
    for (int i = 0; i < N; ++i)
        bfs(i);
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> N >> M;
    memset(G, 0xc0, sizeof(G));
    for (int i = 0; i < M; ++i)
    {
        int u, v, w;
        cin >> u >> v >> w;
        --u, --v;
        G[u][v] = max(G[u][v], (ll)w);
    }
    KM();
    ll res = 0;
    for (int i = 0; i < N; ++i)
        res += lmark[i] + rmark[i];
    cout << res << '\n';
    for (int i = 0; i < N; ++i)
        cout << rmatch[i] + 1 << (i + 1 == N ? '\n' : ' ');
    return 0;
}

你可能感兴趣的:(图论,算法)