• HDU 2255 奔小康,赚钱(KM算法模板)


    解决问题的思路:

    二部图,正确的匹配,卡费用流,使用KM算法。

    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    /*  KM算法
     *   复杂度O(nx*nx*ny)
     *  求最大权匹配
     *   若求最小权匹配。可将权值取相反数,结果取相反数
     *  点的编号从0開始
     */
    const int MAXN = 310;
    const int INF = 0x3f3f3f3f;
    int nx,ny;//两边的点数
    int g[MAXN][MAXN];//二分图描写叙述
    int linker[MAXN],lx[MAXN],ly[MAXN];//y中各点匹配状态。x,y中的点标号
    int slack[MAXN];
    bool visx[MAXN],visy[MAXN];
    
    bool DFS(int x)
    {
        visx[x] = true;
        for(int y = 0; y < ny; y++)
        {
            if(visy[y])continue;
            int tmp = lx[x] + ly[y] - g[x][y];
            if(tmp == 0)
            {
                visy[y] = true;
                if(linker[y] == -1 || DFS(linker[y]))
                {
                    linker[y] = x;
                    return true;
                }
            }
            else if(slack[y] > tmp)
                slack[y] = tmp;
        }
        return false;
    }
    int KM()
    {
        memset(linker,-1,sizeof(linker));
        memset(ly,0,sizeof(ly));
        for(int i = 0;i < nx;i++)
        {
            lx[i] = -INF;
            for(int j = 0;j < ny;j++)
                if(g[i][j] > lx[i])
                    lx[i] = g[i][j];
        }
        for(int x = 0;x < nx;x++)
        {
            for(int i = 0;i < ny;i++)
                slack[i] = INF;
            while(true)
            {
                memset(visx,false,sizeof(visx));
                memset(visy,false,sizeof(visy));
                if(DFS(x))break;
                int d = INF;
                for(int i = 0;i < ny;i++)
                    if(!visy[i] && d > slack[i])
                        d = slack[i];
                for(int i = 0;i < nx;i++)
                    if(visx[i])
                        lx[i] -= d;
                for(int i = 0;i < ny;i++)
                {
                    if(visy[i])ly[i] += d;
                    else slack[i] -= d;
                }
            }
        }
        int res = 0;
        for(int i = 0;i < ny;i++)
            if(linker[i] != -1)
                res += g[linker[i]][i];
        return res;
    }
    int main()
    {
        int n;
        while(scanf("%d",&n) == 1)
        {
            for(int i = 0;i < n;i++)
                for(int j = 0;j < n;j++)
                    scanf("%d",&g[i][j]);
            nx = ny = n;
            printf("%d
    ",KM());
        }
        return 0;
    }
    

  • 相关阅读:
    Frameset 框架
    FHS 文件层次标准
    history 命令
    QT基础走起
    Android中导入jar包v4的错误
    Android工具Eclipse点击卡死或者无响应情况
    让程序飞起来
    Android中报错
    【2019.9.23】NOIP2017 practice exam
    【技巧】时间复杂度
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5042266.html
Copyright © 2020-2023  润新知