zoukankan      html  css  js  c++  java
  • 匈牙利算法代码及理解

    program hungarian;
    
    Type
     rec=record
       e,next:longint;
     end;
    
    Var
     a:array[0..200] of rec;
     b,last:array[0..100] of longint;//last表示每个节点在匹配中的对应节点是什么,last[i]=0表示i是未盖点
     n,m,i,st,ed,ans,top:longint;
     v:array[0..100] of boolean;//表示在“每一轮增广”中某个节点有没有访问过
    
    Procedure add(st,ed:longint);
      begin
      inc(top);
      with a[top] do
        begin
        e:=ed;
        next:=b[st];
      end;
      b[st]:=top;
    end;
    
    function dfs(P:longint):boolean;//P下一条总是要找非匹配边
    var
     u:longint;
     y:^rec;
      begin
      dfs:=false;
      u:=b[p];
      while u<>b[0] do
        begin
        y:=@a[u];
        u:=y^.next;
        if not v[y^.e] then //如果某一个点之前已被访问过表示其已经增广,没有必要再访问
          begin
          v[y^.e]:=true;
          if (last[y^.e]=0) or dfs(last[y^.e]) then 
    //y^.e是未盖点,直接连一条,继续找非匹配边;y^.e是已盖点,先连非匹配边 P - y^.e 再连匹配边 y^.e - last[y^.e] ,之后只要判断dfs(last[y^.e])即可
            begin
            last[y^.e]:=p;
            last[p]:=y^.e;
            exit(true);
          end;
        end;
      end;
      exit(false);
    end;
    
    
      begin
      readln(n,m);
      fillchar(b,sizeof(b),$ff);top:=-1;
      for i:=1 to m do
        begin
        readln(st,ed);
        add(st,ed);
        add(ed,st);
      end;
      ans:=0;
      for i:=1 to n do
        if last[i]=0 then //从未盖点开始增广,但是没有这一行经测试也行= =暂时不知道为什么
          begin
          fillchar(v,sizeof(v),false); //每一轮清空v数组
          inc(ans,ord(dfs(i)));  //每增广一次ans++
        end;
      writeln(ans);
    
    end.
    

     附赠一组数据:

    Input

    6 22
    1 7
    1 8
    1 9
    1 11
    2 7
    2 8
    2 12
    3 7
    3 8
    3 9
    3 10
    3 12
    4 7
    4 8
    4 9
    4 12
    5 7
    5 10
    5 12
    6 9
    6 11
    6 12

    Output

    6

    匹配边

    1 10

    2 8

    3 7

    4 9

    5 12

    6 11

  • 相关阅读:
    C#导出数据—使用Word模板书签的使用
    C#动态调用泛型类、泛型方法
    C#中运算符的介绍和使用
    C#中自定义类型转换
    Linux删除文件后没有释放空间
    Linux下用dd命令测试硬盘的读写速度
    强制关闭或重启Linux系统的几种方法
    前端使用a标签启动本地.exe程序
    Linux 命令别名,让alias永久生效
    Linux 自动删除N小时或分钟前的文件
  • 原文地址:https://www.cnblogs.com/htfy/p/3080675.html
Copyright © 2011-2022 走看看