匹配算法匈牙利算法简介

今天一直在查找匹配算法之类的问题,现在正好有机会和大家分享一下.

    一、二分图的匹配

    匈牙利算法是用来求二分图匹配用的,体具的问题网上都有,这里不再重复。

    二、匈牙利算法及其实现

    先定义一些观点吧:

    (1)、匹配:二分图中的匹配,就是边左的点所对应边右的点的那条边的合集

    (2)、匹配边:在匹配合集中的边

    (3)、未匹配点:义思名顾,就是不是匹配边的端点的点(网上写的是未盖点,但我以为写未匹配点更轻易懂得)

    (4)、错交轨:就是一条在二分图中的路径,这条路径是由匹配边、未匹配边成构的(注意:这里与点是没有关系的

    (5)、增广路:点起与终点都是未匹配点的错交轨

    我们可以演绎出如下定理或者说是定理:

    (1)、当一个二分图有最大匹配时当且仅当它不存在增广路径

    (2)、一条增广路径所包括的边数必为奇数,且未匹配边比匹配边多一条

    (3)、增广路上的第一条边和最后一条边都不是匹配边,增广路的两个顶点分离落在二分图的两个分部中

    (4)、设p为一条包括匹配边的增广路径,那么对增广路上的所有边停止取反操纵,那么就能够到得一个比本来多1的匹配(定理2)

    (5)、主要又不主要的定理:在增广路中,从未匹配点开始,从边左到边右定一是未匹配边,从边右到边左定一是匹配边(这个论结对于大分部论文的懂得都用有)

    面上的定理定一先要懂得,不要过量的纠结于明证,不懂的可以画图画,然后对应的找出个每观点所对应的货色,然后继承:

    由于有了定理4,所以我们可以到得一个基本的算法:对一个图一直的找寻增广路,直到找不到增广路为止,可以明证,当没有增广路时,二分图中定一存在最大匹配——这就是匈牙利算法!!!

    然后就是算法的实现了,可能大分部人看了面上的算法后之都市发生怎么实现的疑难,网上的很多论文都没有讲清楚,面下我谈谈我个人的懂得:

    (1)、为了叙说的便利,我们先把二分图划分为两个合集,边左为L合集,边右为R合集

    (2)、由于匈牙利算法的核心分部是从一个点动身,看看有没有增广路,所以我只在这里叙说如何断判从一个顶点动身有没有增广路

    每日一道理
记不清有多少个夜晚,在我翻阅纸张的指间滑落;记不清有多少支蜡烛,在我的凝视中化为灰烬。逝者如斯,我时时刻刻会听见自己对生命承诺的余音,感到岁月的流转在渐渐稀释我的年少无知,我愿自己是一只上足了发条的时钟,在昼夜不停的流转中留下自己充实的每一刻。

    (3)、设我们动身的点为X(X∈L),然后我们从搜索与X相连接的,不在增广路中的点Y(Y∈R)注意:1、如果在增广路中则说明我们之前经已搜索过该点 2、由定理3,此时X->Y为未匹配边),然后我们看看Y是不是未匹配点(如果是未匹配点,那么我们当然可以直接把X->Y看作是增广路,此时我们从X搜索增广路毕完,搜索结果是增广路只包括X->Y一条边),如果是匹配点,那么我们设H匹配Y(H∈X),然后我们看从H动身有没有增广路(如果从H动身有增广路,那么我们可以把Y连到X了,因原是:1、X->Y是未匹配边 2、从H动身有增广路,由于Y->H是在增广路中的,而且由于定理5(这里我们把定理5看作已知件条),Y->H是匹配边,合结因原1,我们可以得出:[X->Y->H+H的增广路]定一也是也是增广路,此时找到增广路后就能够直接退出了,因为我们的的目只是要找寻一条增广路,而不是最长的增广路

    不知道面上的货色各位有没有看懂,没有看懂的可以给我发Email:[email protected]

    于是序程就出来了,面下附上HDU 2063的代码,这是一道裸题,直接用匈牙利算法就能够做了。

    

var
        n,m,k,i,j,ans,x,y:longint;
        l:array [1..510,1..510] of boolean;
        v:array [1..510] of boolean;
        p:array [1..510] of longint;
function find(x:longint):boolean;//从x开始有没有增广路
var
        i:longint;
begin
        for i:=1 to m do
          if (l[x,i])and(not v[i]) then begin
            v[i]:=true;
            if (p[i]=0)or(find(p[i])) then begin //如果i是未匹配点或者从i的对应点可以找到增广路
              p[i]:=x;  //与i的对应点
              exit(true);
            end;
          end;
        exit(false);
end;
begin
        repeat
          read(k);
          if k=0 then break;
          readln(n,m);
          fillchar(l,sizeof(l),false);
          fillchar(p,sizeof(p),0);
          ans:=0;
          for i:=1 to k do
          begin
            readln(x,y);l[x,y]:=true;
          end;
          for i:=1 to n do //匈牙利的第二个主过程
          begin
            fillchar(v,sizeof(v),false);
            if find(i) then inc(ans);
          end;
          writeln(ans);
        until false;
end.

    匈牙利算法,关键是思想

    Hncsyjc

    转载请注明来源

文章结束给大家分享下程序员的一些笑话语录: 这年头的互联网真是娱乐了中国,网民们从各种各样的“门”里钻来钻去,又有好多“哥”好多“帝”,值得大家品味不已……网络经典语录,关于IT与互联网,经典与您分享!

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