zoukankan      html  css  js  c++  java
  • HDU 2255 奔小康赚大钱 KM算法的简单解释

    KM算法一般用来寻找二分图的最优匹配。

    步骤:

    1.初始化可行标杆

    2.对新加入的点用匈牙利算法进行判断

    3.若无法加入新编,修改可行标杆

    4.重复2.3操作直到找到相等子图的完全匹配。

    各步骤简述:

    1.根据二分图建立2个可行标杆;

    lx为x的可行标杆,初始化lx[i]为与i点相连的最大边

    ly为y的可行标杆,初始化为0.

    可行性的判断条件应为lx[x]+ly[y] >= Map[x][y]。

    2.对于新加入的点用匈牙利算法经行判断,确定改点能否加入旧子图中,形成新子图。

    对于该加入的点有两种可能:

           2.1.找到某个y点,该y点为被连接,则与该点相连,并符合条件

           2.2找到某个y点,该y点已经被某x1点所连接,则对x1点经行深搜,若x1可以找到新的连接点,则修改x1的连接路径,并使x点与y点相连。

    3.如果发现无法再向已有的相等子图中加入边,则证明不再有lx[x]+ly[y]==Map[x][y]成立,那么我们对x和y的可行标杆经行修改。

    当找不到增广路径时,对于搜索过的路径上的XY点,设该路径上的X顶点集为S,Y顶点集为T,对所有在S中的点xi及不在T中的点yj,计算d=min{(L(xi)+L(yj)-weight(xiyj))},从S集中的X标杆中减去d,并将其加入到T集中的Y的标杆中,由于S集中的X标杆减少了,而不在T中的Y标杆不变,相当于这两个集合中的lx(x)+ly(y)变小了,也就是,lx[x]+ly[y]将变小,便有可能有lx[x]+ly[y]==Map[x][y]成立,即可能会加入新的边。

    4.重复2.3过程,知道找到完备相等子图为止。

    时间复杂度:优化后大概为O(n^3);

    代码:

    #include<cstdio>
    #include<stdio.h>
    #include<cstdlib>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    #define INF 0x3f3f3f3f
    #define MAX 1005
    #define mod 1000000007
    
    using namespace std;
    
    int visx[MAX],visy[MAX],lx[MAX],ly[MAX],linker[MAX],slack[MAX],Map[MAX][MAX],n;
    
    bool DFS(int x)
    {
        visx[x]=1;
        for(int y=1;y<=n;y++)
        {
            if(visy[y])
                continue;
            int tmp=lx[x]+ly[y]-Map[x][y];
            if(tmp==0)
            {
                visy[y]=1;
                if(linker[y]==-1 || DFS(linker[y]))
                {
                    linker[y]=x;
                    return true;
                }
            }
            else
            {
                slack[y]=min(slack[y],tmp);
            }
        }
        return false;
    }
    
    int KM()
    {
        int i,j;
        memset(ly,0,sizeof(ly));//初始化可行标杆ly
        memset(linker,-1,sizeof(linker));
        for(i=1; i<=n; i++)//初始化可行标杆lx
        {
            lx[i]=-INF;
            for(j=1; j<=n; j++)
                lx[i]=max(lx[i],Map[i][j]);
        }
    
        for(int x=1; x<=n; x++)
        {
            for(i=1; i<=n; i++)
                slack[i]=INF;
            while(1)
            {
                memset(visx,0,sizeof(visx));
                memset(visy,0,sizeof(visy));
                if(DFS(x))//若可加入直接跳出
                    break;
                int d=INF;
                for(i=1; i<=n; i++)
                {
                    if(!visy[i])
                        d=min(slack[i],d);//否则根据贪心的思想,找到最小的可行标杆修改值
                }
                for(i=1; i<=n; i++)//修改lx标杆
                {
                    if(visx[i])
                        lx[i]-=d;
                }
                for(i=1; i<=n; i++)//修改ly标杆
                {
                    if(visy[i])
                        ly[i]+=d;
                    else
                        slack[i]-=d;//slack由lx[x]+ly[y]-Map[x][y]而来;ly中未标记过的值不变,lx中已标记过的值减少,则slack应减少
                }
            }
        }
        int ans=0;
        for(i=1;i<=n;i++)
        {
            ans+=Map[linker[i]][i];
        }
        return ans;
    }
    
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=n; j++)
                    scanf("%d",&Map[i][j]);
            }
    
            int ans=KM();
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Focal loss and weighted loss学习记录
    学习记录之Focal loss
    caffe学习记录(八) shufflenet学习记录
    caffe学习记录(七) Windows下基于Inter训练的核心加速技术,MKL
    caffe学习记录(六) MobileNet fine tune
    caffe学习记录(五) SSD训练+SSDpelee测试
    caffe学习记录(四) solver
    caffe学习记录(三) Blob,layer Net, solver配置文件的编写
    caffe学习记录(二)
    HTML meta viewport属性说明
  • 原文地址:https://www.cnblogs.com/alan-W/p/5797752.html
Copyright © 2011-2022 走看看