[题目来源]:NOIP基础题集
[关键字]:图论 连通性
[题目大意]:十字绣一针只能正反交错进行,问对于给定图案至少需要多少针。
//=====================================================================================================
[分析]:首先将图划分成不同的连通块,每一块至少要用一针,所以只要计算每个块内要用几针再相加。将正面的连线看作正边,反面的为负边。因为对于每一个点,如果有一条正边则代表正面有一条线,有一条负边则代表反面有一条线,而正负边之差,就是以此点位开始的线的数量,而这样的线必定是某一针的开始。注意,对于每个连通块,如果这样的点为0,则也至少要用一针。
[代码]:
1 type
2 rec = record
3 y, n: longint;
4 end;
5 var
6 n, m, tot: longint;
7 r: array[0..50000] of longint;
8 link: array[0..50000] of longint;
9 e: array[0..400000] of rec;
10 q: array[0..50000] of longint;
11 b, v: array[0..50000] of boolean;
12
13
14 procedure make(x, y: longint);
15 begin
16 inc(tot);
17 b[x] := true;
18 e[tot].y := y;
19 e[tot].n := link[x];
20 link[x] := tot;
21 inc(tot);
22 b[y] := true;
23 e[tot].y := x;
24 e[tot].n := link[y];
25 link[y] := tot;
26 end;
27
28 function floodfill(k: longint):longint;
29 var
30 head, tail, t, temp, x, y: longint;
31 begin
32 head := 1;
33 tail := 1;
34 q[1] := k;
35 temp := abs(r[k]);
36 v[k] := true;
37 while head <= tail do
38 begin
39 x := q[head];
40 t := link[x];
41 while t <> 0 do
42 begin
43 y := e[t].y;
44 if not v[y] then
45 begin
46 inc(tail);
47 q[tail] := y;
48 v[y] := true;
49 temp := temp+abs(r[y]);
50 end;
51 t := e[t].n;
52 end;
53 inc(head);
54 end;
55 temp := temp shr 1;
56 if temp = 0 then temp := 1;
57 exit(temp);
58 end;
59
60 procedure init;
61 var
62 i, j, s1, s2, t1, t2: longint;
63 ch: char;
64 begin
65 readln(n,m);
66 fillchar(b,sizeof(b),false);
67 fillchar(v,sizeof(v),false);
68 fillchar(r,sizeof(r),0);
69 for i := 1 to n do
70 begin
71 for j := 1 to m do
72 begin
73 read(ch);
74 s1 := (i-1)*(m+1)+j;
75 s2 := (i-1)*(m+1)+j+1;
76 t1 := i*(m+1)+j;
77 t2 := i*(m+1)+j+1;
78 if ch = '/' then
79 begin
80 make(s2,t1);
81 inc(r[s2]);
82 inc(r[t1]);
83 end;
84 if ch = '\' then
85 begin
86 make(s1,t2);
87 inc(r[s1]);
88 inc(r[t2]);
89 end;
90 if ch = 'X' then
91 begin
92 make(s1,t2);
93 make(s2,t1);
94 inc(r[s1]);
95 inc(r[s2]);
96 inc(r[t1]);
97 inc(r[t2]);
98 end;
99 end;
100 readln;
101 end;
102 for i := 1 to n do
103 begin
104 for j := 1 to m do
105 begin
106 read(ch);
107 s1 := (i-1)*(m+1)+j;
108 s2 := (i-1)*(m+1)+j+1;
109 t1 := i*(m+1)+j;
110 t2 := i*(m+1)+j+1;
111 if ch = '/' then
112 begin
113 make(s2,t1);
114 dec(r[s2]);
115 dec(r[t1]);
116 end;
117 if ch = '\' then
118 begin
119 make(s1,t2);
120 dec(r[s1]);
121 dec(r[t2]);
122 end;
123 if ch = 'X' then
124 begin
125 make(s1,t2);
126 make(s2,t1);
127 dec(r[s1]);
128 dec(r[s2]);
129 dec(r[t1]);
130 dec(r[t2]);
131 end;
132 end;
133 readln;
134 end;
135 //for i := 1 to (n+1)*(m+1) do writeln(r[i]);
136 end;
137
138 procedure work;
139 var
140 i, temp, ans: longint;
141 begin
142 ans := 0;
143 for i := 1 to (n+1)*(m+1) do
144 if (b[i]) and (not v[i]) then
145 begin
146 temp := floodfill(i);
147 ans := ans+temp;
148 end;
149 writeln(ans);
150 end;
151
152 begin
153 init;
154 work;
155 end.