procedure2012
It's not worth it to know you're not worth it!

[题目来源]:POJ3023

[关键字]:二分图最小路径覆盖

[题目大意]:在一个坐标图中有一些点需要覆盖,每在一个点上覆盖就可在覆盖它上下左右4个点中任一个,问最小放几个。

//=====================================================================================================

[分析]:利用黑白染色法把每一个点都和与之相邻的4个点连边,就构成了一个二分图。要求的就是有最小的点数覆盖全部边,即求最小路径覆盖=最大独立集=所有点-最大匹配由此可以求出最优解。实现方法——匈牙利算法即可。注意的是,这里的点是所有可以放得点*2,而匹配数也是正常匹配数的二倍(A到B连了,B到A也连了),所以最后是n-最大匹配/2。

[代码]:

View Code
  1 program Project1;
2 const
3 dx: array[1..4] of -1..1=(-1,1,0,0);
4 dy: array[1..4] of -1..1=(0,0,1,-1);
5 var
6 tc, n, m, tot: longint;
7 link: array[0..500] of longint;
8 map: array[0..100,0..100] of char;
9 d: array[0..500,0..500] of boolean;
10 b: array[0..500] of boolean;
11
12 function judge(x, y: longint):boolean;
13 begin
14 if (x > n) or (x < 1) or (y > m) or (y < 1) then exit(false);
15 if map[x,y] <> '*' then exit(false);
16 exit(true);
17 end;
18
19 procedure init;
20 var
21 i, j, k, xx, yy, s, s2: longint;
22 begin
23 readln(n,m);
24 tot := 0;
25 for i := 1 to n do
26 begin
27 for j := 1 to m do
28 begin
29 read(map[i,j]);
30 if map[i,j] = '*' then inc(tot);
31 end;
32 readln;
33 end;
34 fillchar(d,sizeof(d),false);
35 for i := 1 to n do
36 for j := 1 to m do
37 if map[i,j] = '*' then
38 begin
39 s := (i-1)*m+j;
40 //writeln(s);
41 for k := 1 to 4 do
42 begin
43 xx := i+dx[k];
44 yy := j+dy[k];
45 //writeln(xx,' ',yy);
46 if judge(xx,yy) then
47 begin
48 s2 := (xx-1)*m+yy;
49 //writeln(s2);
50 d[s,s2] := true;
51 end;
52 end;
53 end;
54 {for i := 1 to n*m do
55 begin
56 for j := 1 to n*m do write(d[i,j],' ');
57 writeln;
58 end;}
59 end;
60
61 function dfs(k: longint):boolean;
62 var
63 i: longint;
64 begin
65 b[k] := false;
66 for i := 1 to n*m do
67 if (d[k,i]) and (b[i]) then
68 begin
69 b[i] := false;
70 if (link[i] = 0) or (dfs(link[i])) then
71 begin
72 link[i] := k;
73 exit(true);
74 end;
75 end;
76 exit(false);
77 end;
78
79 procedure work;
80 var
81 i, j, ans, maxmatch, s: longint;
82 begin
83 maxmatch := 0;
84 fillchar(link,sizeof(link),0);
85 for i := 1 to n do
86 for j := 1 to m do
87 if map[i,j] = '*' then
88 begin
89 s := (i-1)*m+j;
90 fillchar(b,sizeof(b),true);
91 if dfs(s) then inc(maxmatch);
92 end;
93 // writeln(tot,' ',maxmatch);
94 ans := tot-maxmatch div 2;
95 writeln(ans);
96 end;
97
98 begin
99 readln(tc);
100 while tc > 0 do
101 begin
102 init;
103 work;
104 dec(tc);
105 end;
106 end.
posted on 2011-10-18 00:33  procedure2012  阅读(198)  评论(0编辑  收藏  举报