• POJ 1274


    POJ 1274

    题目大意:求二分图最大匹配

    解:初试匈牙利算法,具体的一些问题,总结见程序的同文件夹下。今晚用网络流切下并验证算法正确性。

    2012.02.21 : dinic做法已完成,记得逆边的cost为0!

    {

    如何证明其增广正确性
    会不会因增广而堵塞?
    最优性已经被证明,每次至少能拓展一条边
    二分图的性质可以证明不会出现011的情况,拓展的相邻两条边一定是一条存在另一条不存在
    每次皆从a类节点开始, 用match转跳

    }

    匈牙利
     1 const
    2 maxn=211 << 1;
    3 maxm=(maxn * maxn ) << 1;
    4 type
    5 data=record
    6 dest, next: longint;
    7 end;
    8 var
    9 edge: array[1..maxm]of data;
    10 vect, match: array[1..maxn]of longint;
    11 visit: array[1..maxn]of boolean;
    12 n, m, tot, ans: longint;
    13 procedure add(x, y: longint);
    14 begin
    15 inc(tot);
    16 with edge[tot] do begin
    17 dest := y;
    18 next := vect[x];
    19 vect[x] := tot;
    20 end;
    21 inc(tot);
    22 with edge[tot] do begin
    23 dest := x;
    24 next := vect[y];
    25 vect[y] := tot;
    26 end;
    27 end;
    28
    29 procedure init;
    30 var
    31 i, j, l, x, y: longint;
    32 begin
    33 tot := 0; ans := 0;
    34 fillchar(vect, sizeof(vect), 0);
    35 fillchar(match, sizeof(match), 0);
    36 readln(n, m);
    37 for i := 1 to n do begin
    38 read(l);
    39 for j := 1 to l do begin
    40 read(x);
    41 add(i, x+n);
    42 end;
    43 end;
    44 end;
    45
    46 function dfs(x: longint): boolean;
    47 var
    48 i: longint;
    49 begin
    50 i := vect[x];
    51 while i<>0 do
    52 with edge[i] do begin
    53 if not visit[dest] then begin
    54 visit[dest] := true;
    55 if (match[dest]=0) or (dfs(match[dest])) then begin
    56 match[dest] := x;
    57 exit(true);
    58 end;
    59 end;
    60 i := next;
    61 end;
    62 exit(false);
    63 end;
    64
    65 procedure main;
    66 var
    67 i: longint;
    68 begin
    69 for i := 1 to n do begin
    70 fillchar(visit, sizeof(visit), 0);
    71 if dfs(i) then inc(ans);
    72 end;
    73 end;
    74
    75 procedure print;
    76 begin
    77 writeln(ans);
    78 end;
    79
    80 begin
    81 assign(input,'aaa.in'); reset(input);
    82 while not (seekeof) do begin
    83 init;
    84 main;
    85 print;
    86 end;
    87 close(input);
    88 end.
    dinic
      1 const
    2 maxn=211 << 1;
    3 maxm = (maxn*maxn)<< 1;
    4 bilibili = maxlongint >> 1;
    5 type
    6 data=record
    7 dest, next, cost, op: longint;
    8 end;
    9 var
    10 edge: array[1..maxm]of data;
    11 vect, dist: array[1..maxn]of longint;
    12 n, m, sink, source, ans, tot: longint;
    13 procedure add(x, y, z: longint);
    14 begin
    15 inc(tot);
    16 with edge[tot] do begin
    17 dest := y;
    18 cost := z;
    19 next := vect[x];
    20 vect[x] := tot;
    21 op := tot + 1;
    22 end;
    23 inc(tot);
    24 with edge[tot] do begin
    25 dest := x;
    26 cost := 0;
    27 next := vect[y];
    28 vect[y] := tot;
    29 op := tot - 1;
    30 end;
    31 end;
    32
    33 procedure init;
    34 var
    35 i, j, x, l: longint;
    36 begin
    37 fillchar(vect, sizeof(vect) , 0);
    38 tot := 0;
    39 ans := 0;
    40 readln(n, m);
    41 sink := n + m + 1; source := n + m + 2;
    42 for i := 1 to n do add(sink, i, 1);
    43 for i := 1 to m do add(i+n, source, 1);
    44 for i := 1 to n do begin
    45 read(l);
    46 for j := 1 to l do begin
    47 read(x);
    48 add(i, x + n, bilibili);
    49 end;
    50 end;
    51 end;
    52
    53 function bfs: boolean;
    54 var
    55 q: array[1..maxn]of longint;
    56 head, tail, i, u: longint;
    57 begin
    58 filldword(dist, sizeof(dist)>> 2, bilibili);
    59 head := 0; tail := 1;
    60 q[tail] := sink; dist[sink] := 1;
    61 repeat
    62 head := head mod maxn + 1;
    63 u := q[head]; i := vect[u];
    64 while i<>0 do
    65 with edge[i] do begin
    66 if (cost > 0) and (dist[dest] > dist[u] + 1) then begin
    67 dist[dest] := dist[u] + 1;
    68 tail := tail mod maxn + 1;
    69 q[tail] := dest;
    70 end;
    71 i := next;
    72 end;
    73 if dist[source] <> bilibili then break;
    74 until head=tail;
    75 exit(dist[source] <> bilibili);
    76 end;
    77
    78 function min(a, b: longint): longint;
    79 begin if a<b then exit(a) else exit(b); end;
    80
    81 function dinic(x, flow: longint): longint;
    82 var
    83 i, tmp: longint;
    84 begin
    85 if x = source then exit(flow);
    86 dinic := 0;
    87 i := vect[x];
    88 while i<>0 do
    89 with edge[i] do begin
    90 if (cost > 0)and(dist[dest]=dist[x]+1) then begin
    91 tmp := dinic(dest, min(flow, cost));
    92 dinic := dinic + tmp;
    93 flow := flow - tmp;
    94 cost := cost - tmp;
    95 edge[op].cost := edge[op].cost + tmp;
    96 if flow = 0 then break;
    97 end;
    98 i := next;
    99 end;
    100 if dinic = 0 then dist[x] := -1;
    101 end;
    102
    103 procedure main;
    104 begin
    105 while bfs do
    106 begin
    107 ans := ans + dinic(sink, bilibili);
    108 end;
    109 end;
    110
    111 procedure print;
    112 begin
    113 writeln(ans);
    114 end;
    115
    116 begin
    117 assign(input,'aaa.in'); reset(input);
    118 while not seekeof do begin
    119 init;
    120 main;
    121 print;
    122 end;
    123 close(input);
    124 end.



  • 相关阅读:
    更易型算法(Manipulating Algorithms)
    迭代器之配接器
    Windows下BBv2安装编译libtorrent
    swfupload简单使用
    Openx 中文编码解决方案
    常见c语言编译错误解析(转)
    新建一个scrapy项目
    判断两个日期的时间部分之差
    javascript弹出子窗口并返回值
    转:浅析ASP.NET中页面传值的几种方法
  • 原文地址:https://www.cnblogs.com/wmzisfoolish/p/2435172.html
Copyright © 2020-2023  润新知