zoukankan      html  css  js  c++  java
  • 【km算法模板+总结】

    今天下午看了一下午的km算法,因为大佬的博客介绍非常简短,所以自己一直没有弄清楚一些细节问题,好在回来翻到了一个比较好的csdn专栏,介绍比较详细,自己才算弄懂了很多疑惑的地方,二分图最佳完美匹配

    总结一下算法:

    思想:km算法就是改变一些可行点的标号,不断增加图中可行边的总数,直到图中存在仅由可行边组成的完美匹配为止。核心部分就是控制修改可行顶标的值直到最终可到达一个完美匹配。

    流程:1)初始化可行顶标lx和ly的值(ly=0显然是可行的,保证任意x一个x方点至少一条可行边)

       2)从每个x方点开始dfs增广,用匈牙利算法寻找相等子图的完备匹配。

       3)如果没有找到增广路,改变可行顶标的值。

       4)重复2)3)直到找到相等子图的完备匹配。

    注意两点:一是只找可行边,二是要把搜索过程中遍历到的X方点全部记下来,以便进行后面的修改

    int dfs(int x)//完全匹配 
    {
        int y,tmp;
        visx[x] = 1;
        for(y = 1; y <= ny; y ++)
        {
            if(!visy[y])
            {
                tmp = lx[x] + ly[y] - w[x][y];
                if(!tmp)
                {
                    visy[y] = 1;
                    if(linker[y] == -1||dfs(linker[y]))
                    {
                        linker[y] = x;
                        return 1;
                    }
                }
                else if(d > tmp)//取最小的不在增广轨中的常数d 
                    d = tmp;
            }
        }
        return 0;
    }
    
    int KM()//求最大匹配 
    {
        int sum,x,i,j;
        memset(linker,-1,sizeof(linker));
        memset(ly,0,sizeof(ly));
        for(i = 1; i <= nx; i ++)
            for(j = 1,lx[i] = -INF; j <= ny; j ++)
                if(lx[i] < w[i][j])
                    lx[i] = w[i][j];//初始化为权值最大的边的权值 
                    
        for(x = 1; x <= nx; x++)
        {
            while(1)
            {
                d = INF;//常数d每次都要进行初始化 
                memset(visx,0,sizeof(visx));//每次dfs都要进行更新 
                memset(visy,0,sizeof(visy));
                if(dfs(x))
                    break;
                for(i = 1; i <= nx; i ++)
                    if(visx[i])//在增广轨中的x点标减去常数d 
                        lx[i] -= d;
                for(i = 1; i <= ny; i ++)
                    if(visy[i])//在增广轨中的y点标加上常数d 
                        ly[i] += d;
            }
        }
        sum = 0;
        for(i = 1; i <= ny; i ++)
            if(linker[i]!=-1)
                sum += w[linker[i]][i]; 
        return sum;
    }
  • 相关阅读:
    I NEED A OFFER!
    水题 Codeforces Round #303 (Div. 2) A. Toy Cars
    模拟 HDOJ 5099 Comparison of Android versions
    模拟 HDOJ 5095 Linearization of the kernel functions in SVM
    贪心 HDOJ 5090 Game with Pearls
    Kruskal HDOJ 1863 畅通工程
    Kruskal HDOJ 1233 还是畅通工程
    并查集 HDOJ 1232 畅通工程
    DFS/并查集 Codeforces Round #286 (Div. 2) B
    水题 Codeforces Round #286 (Div. 2) A Mr. Kitayuta's Gift
  • 原文地址:https://www.cnblogs.com/hellocheng/p/7354979.html
Copyright © 2011-2022 走看看