[HDOJ3622]Bomb Game

二分+2SAT验证~

View Code
1 #include <cstdio>
2 #include <cstring>
3
4  /*
5
6 * 2-SAT
7 * 标号从1开始
8
9  */
10
11 #define OO(i) ((i & 1) ? (i + 1) : (i - 1))
12
13 class B_SAT
14 {
15 private:
16 const static int NK = 2;
17 const static int MAXV = 16050;
18 const static int MAXE = 40100;
19 const static int INF = 0x7F7F7F7F;
20
21 int nv;
22
23 int top1;
24 int stk1[MAXV];
25 int top2;
26 int stk2[MAXV];
27
28 int times;
29 int npart;
30 int low[MAXV];
31
32 int cor[MAXV];
33
34 int belong[MAXV];
35
36 int list[MAXV];
37 int queue[MAXV];
38 int degree[MAXV];
39 bool topovst[MAXV];
40
41 struct List
42 {
43 int u;
44 int v;
45 List * next;
46 };
47
48 List pool[NK][MAXE];
49 List * pp[NK];
50 List * head[NK][MAXV];
51
52 List * create(int u,int v,List * * pp,List * next)
53 {
54 (*pp)->u = u;
55 (*pp)->v = v;
56 (*pp)->next = next;
57 return (*pp)++;
58 }
59 void dfs(int v);
60 void Gabow();
61 void Rebuild();
62 void Topo();
63
64 public:
65 void Init(int _nv);
66 void addEdge(int u,int v,int idx);
67 bool solvable();
68 void SAT();
69 };
70
71 void B_SAT::dfs(int v)
72 {
73 low[v] = ++times;
74 stk1[++top1] = v;
75 stk2[++top2] = v;
76 for (List * tp = head[0][v];tp;tp = tp->next)
77 {
78 int u = tp->v;
79 if (low[u] == INF)
80 dfs(u);
81 else if (belong[u] == INF)
82 while (low[stk2[top2]] > low[u])
83 --top2;
84 }
85
86 if (stk2[top2] == v)
87 {
88 --top2;
89 ++npart;
90 do
91 {
92 belong[stk1[top1]] = npart;
93 }
94 while (stk1[top1--] != v);
95 }
96 }
97
98 void B_SAT::Gabow()
99 {
100 top1 = top2 = times = npart = 0;
101 memset(low,0x7F,(nv + 2) * sizeof(low[0]));
102 memset(belong,0x7F,(nv + 2) * sizeof(belong[0]));
103 for (int i = 1;i <= nv;i++)
104 if (low[i] == INF)
105 dfs(i);
106 }
107
108 void B_SAT::Rebuild()
109 {
110 memset(degree,0,(nv + 2) * sizeof(degree[0]));
111
112 for (List * tp = pool[0];tp != pp[0];tp++)
113 {
114 int u = belong[tp->u];
115 int v = belong[tp->v];
116 if (u != v)
117 {
118 addEdge(v,u,1);
119 degree[u]++;
120 }
121 }
122 }
123
124 void B_SAT::Topo()
125 {
126 int qh = -1;
127 int qe = -1;
128 int cnt = 0;
129
130 memset(topovst,false,(nv + 2) * sizeof(topovst[0]));
131
132 for (int i = 1;i <= npart;i++)
133 if (degree[i] == 0 && !topovst[i])
134 {
135 topovst[i] = true;
136 list[++cnt] = i;
137 queue[++qe] = i;
138 while (qh != qe)
139 {
140 int u = queue[++qh];
141 for (List * p = head[1][u];p;p = p->next)
142 {
143 degree[p->v]--;
144 if (degree[p->v] == 0 && !topovst[p->v])
145 {
146 list[++cnt] = p->v;
147 queue[++qe] = p->v;
148 topovst[p->v] = true;
149 }
150 }
151 }
152 }
153
154 memset(topovst,true,(npart + 2) * sizeof(topovst[0]));
155 for (int i = 1;i <= cnt;i++)
156 if (topovst[list[i]])
157 topovst[cor[list[i]]] = false;
158 }
159
160 void B_SAT::Init(int _nv)
161 {
162 nv = _nv;
163
164 pp[0] = pool[0];
165 pp[1] = pool[1];
166 memset(head,0,sizeof(head));
167 }
168
169 void B_SAT::addEdge(int u,int v,int idx)
170 {
171 head[idx][u] = create(u,v,&pp[idx],head[idx][u]);
172 }
173
174 bool B_SAT::solvable()
175 {
176 Gabow();
177 int lim = nv / 2;
178 for (int i = 1;i <= lim;i++)
179 {
180 if (belong[2 * i - 1] == belong[2 * i])
181 return false;
182 cor[belong[2 * i - 1]] = belong[2 * i];
183 cor[belong[2 * i]] = belong[2 * i - 1];
184 }
185 return true;
186 }
187
188 void B_SAT::SAT()
189 {
190 Rebuild();
191 Topo();
192 for (int i = 1;i <= nv;i++)
193 if (topovst[belong[i]])
194 printf("%d\n",i);
195 }
196
197 B_SAT sat;
198
199 const int SIZE = 128;
200 const double EPS = 0.0001;
201
202 struct PP
203 {
204 int x;
205 int y;
206 };
207
208 struct LL
209 {
210 PP a;
211 PP b;
212 };
213
214 LL in[SIZE];
215
216 bool judge(const PP & a,const PP & b,double mid)
217 {
218 return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) <= 4 * mid * mid;
219 }
220
221 bool isok(int nv,double mid)
222 {
223 sat.Init(nv << 1);
224 for (int i = 1;i <= nv;i++)
225 for (int j = i + 1;j <= nv;j++)
226 {
227 if (judge(in[i].a,in[j].a,mid))
228 {
229 int a = (i << 1) - 1;
230 int b = (j << 1) - 1;
231 sat.addEdge(a,OO(b),0);
232 sat.addEdge(b,OO(a),0);
233 }
234 if (judge(in[i].a,in[j].b,mid))
235 {
236 int a = (i << 1) - 1;
237 int b = (j << 1);
238 sat.addEdge(a,OO(b),0);
239 sat.addEdge(b,OO(a),0);
240 }
241 if (judge(in[i].b,in[j].a,mid))
242 {
243 int a = (i << 1);
244 int b = (j << 1) - 1;
245 sat.addEdge(a,OO(b),0);
246 sat.addEdge(b,OO(a),0);
247 }
248 if (judge(in[i].b,in[j].b,mid))
249 {
250 int a = (i << 1);
251 int b = (j << 1);
252 sat.addEdge(a,OO(b),0);
253 sat.addEdge(b,OO(a),0);
254 }
255 }
256
257 return sat.solvable();
258 }
259
260
261 int main()
262 {
263 int nv;
264
265 while (scanf("%d",&nv) != EOF)
266 {
267 for (int i = 1;i <= nv;i++)
268 scanf("%d %d %d %d",&in[i].a.x,&in[i].a.y,&in[i].b.x,&in[i].b.y);
269
270 double high = 30000;
271 double low = 0;
272 double mid;
273 double ans;
274
275 while (high - low > EPS)
276 {
277 mid = (low + high) / 2;
278 if (isok(nv,mid))
279 {
280 low = mid;
281 ans = mid;
282 }
283 else high = mid;
284 }
285
286 printf("%.2lf\n",ans);
287 }
288 return 0;
289 }
原文地址:https://www.cnblogs.com/debugcool/p/HDOJ3622.html