• 匈牙利算法


    (一)首先明确匈牙利算法是干嘛滴?

        匈牙利算法是解决二部图最大匹配问题滴。

    (二)算法的核心思想:不断寻找增广路径,每找到一条增广路径,就通过异或操作使匹配边数加一,直到找不到增广路径,算法结束。

    (三)算法的基本步骤:

        (1)任取二部图G(X,Y)的匹配M,若M饱和X,则停止。若M不能饱和X,则取X的未标记的M非饱和点x。(标记的点表示经过此点不存在增广路)令S={x},T= Ø.(T集合中的点表示N(S)中已经加入增广路的点)(当不存非饱和点或者所有非饱和点都被标记,算法结束)

        (2)若N(S)=T,(S集合中的所有点的对应项都是已经走过的的点)则返回(1),即无经过x的增广通路,标记x。否则,取y ∈N(S)-T。

        (3)若y是M饱和的,则存在z ∈X-S使yz ∈M.令S=S∪{z},T=T∪{y},转入(2)。若y是M非饱和的,则G中存在以x为起点y为终点的M增广通路P。用令M=M异或EP即将这条增广路上的已匹配边与未匹配边对换,得到比原来匹配数多一的新匹配,转入(1).

    (四)算法的核心结构

     1 void hungary()//匈牙利算法
     2 {
     3     for i->1 to n
     4         if (从i的对应项出有可增广路)
     5             匹配数++;
     6     输出 匹配数;
     7 }
     8 bool  findpath(k)//寻找从k出发的对应项出的可增广路
     9 {
    10     while (从邻接表中列举k能关联到顶点j){
    11         if (j不在增广路上){
    12             把j加入增广路;
    13             if (j是未匹配点 或者 从j的对应项出发有可增广路)
    14                 修改j的对应项为k;//也就是说边(k,j)匹配,j对应匹配到k上
    15                 则从k的对应项出有可增广路,返回true;
    16             }
    17         }
    18     }
    19     则从k的对应项出没有可增广路,返回false;
    20 }

    (五)算法的核心代码

     1 bool findpath(int x)
     2 {
     3     visx[x] = true;
     4     for(int y = 1 ; y <= ny ; ++y){
     5         if(!visy[y] && (lx[x] + ly[y] == G[x][y])){
     6             visy[y] = true;
     7             if(match[y] == -1 || findpath(match[y])){
     8                 match[y] = x;
     9                 return true;
    10             }
    11         }
    12     }
    13     return false;
    14 }

    (六)下面放一道已经AC的题HDU1469

    http://poj.org/problem?id=1469

     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 #define P 110
     5 #define N 310
     6 int map[P][N];
     7 int match[N];
     8 bool use[N];
     9 int p, n;
    10 
    11 bool find(int u) //u是课程
    12 {
    13     for(int i = 1; i <= n; ++i)
    14     {
    15         if(!use[i] && map[u][i]) //标记匹配的学生
    16         {
    17             use[i] = true;
    18             if(match[i] == - 1 || find(match[i]))
    19             {
    20                 match[i] = u;
    21                 return true;
    22             }
    23         }
    24     }
    25     return false;
    26 }
    27 
    28 int sum()
    29 {
    30     int ans = 0;
    31     for(int i = 1; i <= p; ++i) //统计匹配的课程
    32     {
    33         memset(use, false, sizeof(use));
    34         if(find(i))
    35             ans++;
    36     }
    37     return ans;
    38 }
    39 
    40 int main()
    41 {
    42     int T;
    43     int m, temp, ans;
    44     scanf("%d", &T);
    45     while(T--)
    46     {
    47         memset(map, 0, sizeof(map));
    48         memset(match, -1, sizeof(match));
    49         scanf("%d%d", &p, &n);
    50         for(int i = 1; i <= p; ++i)
    51         {
    52             scanf("%d", &m);
    53             for(int j = 1; j <= m; ++j)
    54             {
    55                 scanf("%d", &temp);
    56                 map[i][temp] = 1; //j号学生喜欢i号课程
    57             }
    58         }
    59         ans = sum();
    60         printf("%s
    ", ans == p ? "YES" : "NO");
    61     }
    62     return 0;
    63 }

    今天刚学完匈牙利算法,趁热打铁,赶快写篇博客加深一下印象!看不懂你打我!!!不认真看打死你!!!



  • 相关阅读:
    inline-block图文布局
    display: inline-block换行问题
    前端Fiddler高级调试技巧
    开发人员linux命令总结
    随笔-系统安装
    Fiddler高阶技能-项目文件代理
    译:如何使用时间轴工具
    jquery 选择器之children与find
    ASP.NET 大文件下载的实现思路及代码
    Git 使用指南
  • 原文地址:https://www.cnblogs.com/--lr/p/6759213.html
Copyright © 2020-2023  润新知