最小覆盖问题,跟3041差不多,只不过有了不能覆盖点的限制,首先横竖染色,那么每个水坑要么没横着的覆盖,要么被竖着的覆盖,用染出色的该点木板颜色连边,求最大匹配即可。
View Code
1 program pku2226(input,output);
2 var
3 map : array[0..51,0..51] of char;
4 x,y : array[0..51,0..51] of longint;
5 f : array[0..2500,0..2500] of boolean;
6 v : array[0..2500] of boolean;
7 lk : array[0..2500] of longint;
8 n,m : longint;
9 ll,rr : longint;
10 procedure init;
11 var
12 i,j : longint;
13 begin
14 readln(n,m);
15 for i:=1 to n do
16 begin
17 for j:=1 to m do
18 read(map[i,j]);
19 readln;
20 end;
21 fillchar(x,sizeof(x),255);
22 fillchar(y,sizeof(y),255);
23 end; { init }
24 procedure make_graph();
25 var
26 i,j : longint;
27 tot : longint;
28 begin
29 tot:=0;
30 for i:=1 to n do
31 for j:=1 to m do
32 begin
33 if map[i,j]='.' then
34 continue
35 else
36 begin
37 if x[i,j-1]<>-1 then
38 x[i,j]:=x[i,j-1]
39 else
40 begin
41 inc(tot);
42 x[i,j]:=tot;
43 end;
44 end;
45 end;
46 ll:=tot+1;
47
48 for i:=1 to m do
49 for j:=1 to n do
50 begin
51 if map[j,i]='.' then
52 continue
53 else
54 begin
55 if y[j-1,i]<>-1 then
56 y[j,i]:=y[j-1,i]
57 else
58 begin
59 inc(tot);
60 y[j,i]:=tot;
61 end;
62 end;
63 end;
64 rr:=tot;
65
66 fillchar(f,sizeof(f),false);
67 for i:=1 to n do
68 for j:=1 to m do
69 if map[i,j]='*' then
70 f[x[i,j],y[i,j]]:=true;
71 end; { make_graph }
72 function find(now :longint ):boolean;
73 var
74 i : longint;
75 begin
76 for i:=ll to rr do
77 if (not v[i])and(f[now,i]) then
78 begin
79 v[i]:=true;
80 if (lk[i]=0)or(find(lk[i])) then
81 begin
82 lk[i]:=now;
83 exit(true);
84 end;
85 end;
86 exit(false);
87 end; { find }
88 function main:longint;
89 var
90 i : longint;
91 begin
92 main:=0;
93 fillchar(lk,sizeof(lk),0);
94 for i:=1 to ll-1 do
95 begin
96 fillchar(v,sizeof(v),false);
97 if find(i) then
98 inc(main);
99 end;
100 end; { main }
101 begin
102 while not eof do
103 begin
104 init;
105 make_graph;
106 writeln(main);
107 end;
108 end.