【模板】二分图最大权完美匹配KM算法

题目参见洛谷P4014

模板贴一下。

struct part { int ex[MAXN]; bool vis[MAXN]; } X, Y;
int n, match[MAXN], slack[MAXN], fit[MAXN][MAXN];
bool DFS(int x)
{
    X.vis[x] = true;
    for (int y = 1;y <= n;y++)
    {
        if (Y.vis[y]) continue;
        int gap = X.ex[x] + Y.ex[y] - fit[x][y];
        if (gap == 0)
        {
            Y.vis[y] = true;
            if (match[y] == -1 || DFS(match[y])) 
            {
                match[y] = x;
                return true;
            }
        }
        else slack[y] = min(slack[y], gap);
    }
    return false;
}
int KM()
{
    memset(match, -1, sizeof match);
    memset(Y.ex, 0, sizeof Y.ex);
    for (int i = 1;i <= n;i++)
    {
        X.ex[i] = fit[i][1];
        for (int j = 2;j <= n;j++) 
            X.ex[i] = max(X.ex[i], fit[i][j]);
    }
    for (int i = 1;i <= n;i++)
    {
        memset(slack, 127, sizeof slack);
        while (true)
        {
            memset(X.vis, false, sizeof X.vis);
            memset(Y.vis, false, sizeof Y.vis);
            if (DFS(i)) break;
            int d = INT_MAX;
            for (int j = 1;j <= n;j++)
                if (!Y.vis[j])
                    d = min(d, slack[j]);
            for (int j = 1;j <= n;j++)
            {
                if (X.vis[j]) X.ex[j] -= d;
                if (Y.vis[j]) Y.ex[j] += d;
                else slack[j] -= d;
            }
        }
    }
    int ans = 0;
    for (int i = 1;i <= n;i++)
        ans += fit[match[i]][i];
    return ans;
}
分成两个part,X和Y,ex[]表示期望值,vis[]表示每轮是否参与匹配,match[]表示Xpart每轮匹配到的Y的编号。slack[]表示Y要能被X匹配到最少需要多少期望值。具体思想还请Baidu一下。

你可能感兴趣的:(图论,二分图)