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.



posted @ 2012-04-06 19:40  F.D.His.D  阅读(200)  评论(0编辑  收藏  举报