2226

1 /*
2 这个题目有点意思
3
4 构图需分析,和3041有区别
5
6 3041,是一行可以覆盖。所以在那个题目中,每行和列可作为顶点
7
8 现在的题目,是每段可覆盖,所以每个段作为顶点,如果交叉则有边。
9
10 这样图就构成了
11 */
12
13 // include file
14 #include <cstdio>
15 #include <cstdlib>
16 #include <cstring>
17 #include <cmath>
18 #include <cctype>
19 #include <ctime>
20
21 #include <iostream>
22 #include <sstream>
23 #include <fstream>
24 #include <iomanip>
25 #include <bitset>
26 #include <strstream>
27
28 #include <algorithm>
29 #include <string>
30 #include <vector>
31 #include <queue>
32 #include <set>
33 #include <list>
34 #include <functional>
35
36 using namespace std;
37
38 // typedef
39 typedef long long LL;
40 typedef unsigned long long ULL;
41
42 //
43 #define read freopen("in.txt","r",stdin)
44 #define write freopen("out.txt","w",stdout)
45 #define FORi(a,b,c) for(int i=(a);i<(b);i+=c)
46 #define FORj(a,b,c) for(int j=(a);j<(b);j+=c)
47 #define FORk(a,b,c) for(int k=(a);k<(b);k+=c)
48 #define FORp(a,b,c) for(int p=(a);p<(b);p+=c)
49
50 #define FF(i,a) for(int i=0;i<(a);i+++)
51 #define FFD(i,a) for(int i=(a)-1;i>=0;i--)
52 #define Z(a) (a<<1)
53 #define Y(a) (a>>1)
54
55 const double eps = 1e-6;
56 const double INFf = 1e10;
57 const int INFi = 1000000000;
58 const double Pi = acos(-1.0);
59
60 template<class T> inline T sqr(T a){return a*a;}
61 template<class T> inline T TMAX(T x,T y)
62 {
63 if(x>y) return x;
64 return y;
65 }
66 template<class T> inline T TMIN(T x,T y)
67 {
68 if(x<y) return x;
69 return y;
70 }
71 template<class T> inline void SWAP(T &x,T &y)
72 {
73 T t = x;
74 x = y;
75 y = t;
76 }
77 template<class T> inline T MMAX(T x,T y,T z)
78 {
79 return TMAX(TMAX(x,y),z);
80 }
81
82
83 // code begin
84
85 #define MAXN 2510
86 int R,C,ans;
87 vector<int> G[MAXN];
88 int mt[MAXN];
89 bool used[MAXN];
90 char in[55][55];
91
92 struct node
93 {
94 int flag; //
95 int s;
96 int e;
97 };
98
99 node row[MAXN];
100 node col[MAXN];
101
102 bool hungarian_MM(int i)
103 {
104 FORj(0,G[i].size(),1)
105 {
106 if(!used[ G[i][j] ])
107 {
108 used[ G[i][j] ] = true;
109 if( mt[G[i][j]]==-1 || hungarian_MM(mt[G[i][j]]))
110 {
111 mt[G[i][j]] = i;
112 return true;
113 }
114 }
115 }
116 return false;
117 }
118
119 bool Intersect(int i,int j)
120 {
121 // 行,lie
122 if( col[j].flag>=row[i].s&&col[j].flag<=row[i].e && row[i].flag>=col[j].s&&row[i].flag<=col[j].e )
123 return true;
124 return false;
125 }
126
127 int main()
128 {
129 read;
130 write;
131 int rs,cs;
132 while(scanf("%d %d",&R,&C)!=-1)
133 {
134 FORi(0,R,1)
135 {
136 scanf("%s",in[i]);
137 }
138 // 求出所有的行段
139 rs = 0;
140 FORi(0,R,1)
141 {
142 // in[i];
143 int s = 0,e;
144 while(true)
145 {
146 while(s<C&&in[i][s]!='*') s++;
147 if(s>=C) break;
148 e = s;
149 while(e<C&&in[i][e]=='*') e++;
150 node t;
151 t.s = s;
152 if(e>=C)
153 {
154 t.e = C-1;
155 t.flag = i; // 表示行
156 row[rs++] = t;
157 break;
158 }
159 t.e = e-1;
160 t.flag = i;
161 row[rs++]=t;
162 s=e;
163 }
164 }
165 // 求出所有的列断
166 cs = 0;
167 FORi(0,C,1)
168 {
169 int s = 0,e;
170 while(true)
171 {
172 while(s<R&&in[s][i]!='*') s++;
173 if(s>=R) break;
174 e = s;
175 while(e<R&&in[e][i]=='*') e++;
176 node t;
177 t.s = s;
178 if(e>=R)
179 {
180 t.e = R-1;
181 t.flag = i; // 表示列
182 col[cs++] = t;
183 break;
184 }
185 t.e = e-1;
186 t.flag = i;
187 col[cs++] = t;
188 s = e;
189 }
190 }
191 //printf("%d %d\n",rs,cs);
192 //
193 FORi(0,rs,1)
194 {
195 FORj(0,cs,1)
196 {
197 //判断row[i] 和 col[j]是否能够相交
198 if( Intersect(i,j)) G[i].push_back(j);
199 }
200 }
201
202
203 memset(mt,-1,sizeof(int)*MAXN);
204 ans = 0;
205
206 FORi(0,rs,1)
207 {
208 memset(used,0,sizeof(bool)*MAXN);
209 if( hungarian_MM(i) )
210 {
211 ans++;
212 }
213 }
214
215 printf("%d\n",ans);
216 }
217 return 0;
218 }
posted @ 2011-03-04 21:39  AC2012  阅读(1327)  评论(0编辑  收藏  举报