1
/*
2 门是按顺序打开的,这点非常重要。
3
4 2SAT,建图,判断有有解
5 关于限制条件,对于key pair.有关系 a and b = 0,最多只能用1个,a1b0,a0b1,a0b0
6 对于门上的key pair,有关系 a or b = 1,只要有一个是1就行,a1b1 a1b0 a0b1
7 关系转化为边,可参考3678
8
9 可用二分加速
10 */
11
12 // include file
13 #include < cstdio >
14 #include < cstdlib >
15 #include < cstring >
16 #include < cmath >
17 #include < cctype >
18 #include < ctime >
19
20 #include < iostream >
21 #include < sstream >
22 #include < fstream >
23 #include < iomanip >
24 #include < bitset >
25 #include < strstream >
26
27 #include < algorithm >
28 #include < string >
29 #include < vector >
30 #include < queue >
31 #include < set >
32 #include < list >
33 #include < functional >
34
35 using namespace std;
36
37 // typedef
38 typedef long long LL;
39 typedef unsigned long long ULL;
40
41 //
42 #define read freopen("in.txt","r",stdin)
43 #define write freopen("out.txt","w",stdout)
44 #define FORi(a,b) for(int i=(a);i<(b);i++)
45 #define FORj(a,b) for(int j=(a);j<(b);j++)
46
47 #define FF(i,a) for(int i=0;i<(a);i+++)
48 #define FFD(i,a) for(int i=(a)-1;i>=0;i--)
49 #define Z(a) (a<<1)
50 #define Y(a) (a>>1)
51
52 const double eps = 1e - 11 ;
53 const double Pi = acos( - 1.0 );
54
55 template < class T > inline T sqr(T a){ return a * a;}
56 template < class T > inline T TMAX(T x,T y)
57 {
58 if (x > y) return x;
59 return y;
60 }
61 template < class T > inline T TMIN(T x,T y)
62 {
63 if (x < y) return x;
64 return y;
65 }
66 template < class T > inline T MMAX(T x,T y,T z)
67 {
68 return TMAX(TMAX(x,y),z);
69 }
70
71
72 // code begin
73 #define MAXN 5010
74
75 struct node
76 {
77 int a,b;
78 };
79
80 node key[MAXN];
81 node door[MAXN];
82
83 vector < int > G[MAXN];
84
85 int scc;
86 int cnt;
87 int used[MAXN];
88 int stk1[MAXN],top1;
89 int stk2[MAXN],top2;
90 int isin[MAXN];
91 int dfn[MAXN];
92 int low[MAXN];
93 int id[MAXN];
94 int N,M;
95
96 void gabow_scc( int i)
97 {
98 used[i] = true ;
99 stk1[top1 ++ ] = i;
100 stk2[top2 ++ ] = i;
101 dfn[i] = cnt ++ ;
102 isin[i] = true ;
103
104 FORj( 0 ,G[i].size() )
105 {
106 if ( ! used[ G[i][j] ])
107 {
108 gabow_scc(G[i][j]);
109 }
110 else if (isin[G[i][j]])
111 {
112 while (dfn[stk2[top2 - 1 ]] > dfn[G[i][j]])
113 top2 -- ;
114 }
115 }
116
117 if (i == stk2[top2 - 1 ])
118 {
119 top2 -- ;
120 int w;
121 do
122 {
123 w = stk1[ -- top1];
124 isin[w] = false ;
125 id[w] = scc;
126 } while (w != i);
127
128 scc ++ ;
129 }
130 }
131
132 void tarjan_scc( int i)
133 {
134 used[i] = true ;
135 stk1[top1 ++ ] = i;
136 dfn[i] = cnt;
137 low[i] = cnt;
138 cnt ++ ;
139 isin[i] = true ;
140
141 FORj( 0 ,G[i].size())
142 {
143 if ( ! used[ G[i][j] ])
144 {
145 tarjan_scc(G[i][j]);
146 low[i] = TMIN(low[i],low[G[i][j]]);
147 }
148 else if (isin[G[i][j]])
149 {
150 low[i] = TMIN(low[i],dfn[G[i][j]]);
151 }
152 }
153
154 if (dfn[i] == low[i])
155 {
156 int w;
157 do
158 {
159 w = stk1[ -- top1];
160 isin[w] = false ;
161 id[w] = scc;
162 } while (w != i);
163 scc ++ ;
164 }
165 }
166
167 void build_G( int sz)
168 {
169 FORi( 0 ,N * 4 )
170 {
171 G[i].clear();
172 }
173 int a,b;
174 FORi( 0 ,N)
175 {
176 // a and b = 0
177 a = key[i].a;
178 b = key[i].b;
179 G[ 2 * a + 1 ].push_back( 2 * b);
180 G[ 2 * b + 1 ].push_back( 2 * a);
181 }
182 FORi( 0 ,sz)
183 {
184 // a or b = 1
185 a = door[i].a;
186 b = door[i].b;
187 G[ 2 * a].push_back( 2 * b + 1 );
188 // G[2*b+1].push_back(2*a);
189 G[ 2 * b].push_back( 2 * a + 1 );
190 // G[2*a+1].push_back(2*b);
191 }
192 }
193
194 bool SAT( int mid)
195 {
196 if (mid == 0 ) return true ;
197 memset(used, 0 , sizeof (used));
198 memset(id, 0 , sizeof (id));
199 top1 = top2 = 0 ;
200 cnt = 1 ;
201 scc = 1 ;
202 memset(isin, 0 , sizeof (isin));
203 memset(dfn, 0 , sizeof (dfn));
204 memset(low, 0 , sizeof (low));
205 FORi( 0 ,N * 4 )
206 {
207 if ( ! used[i])
208 {
209 // gabow_scc(i);
210 tarjan_scc(i);
211 }
212 }
213
214 FORi( 0 ,N * 2 )
215 {
216 if (id[ 2 * i] == id[ 2 * i + 1 ])
217 return false ;
218 }
219 return true ;
220 }
221
222 int main()
223 {
224 read;
225 write;
226 while (scanf( " %d %d " , & N, & M) !=- 1 )
227 {
228 if (N + M == 0 ) break ;
229
230 int a,b;
231 FORi( 0 ,N)
232 {
233 scanf( " %d %d " , & a, & b);
234 key[i].a = a;
235 key[i].b = b;
236 }
237
238 FORi( 0 ,M)
239 {
240 scanf( " %d %d " , & a, & b);
241 door[i].a = a;
242 door[i].b = b;
243 }
244
245 // 0..M
246 int L = 0 ,R = M + 1 ,ans = 0 ;
247
248 while (L < R)
249 {
250 int mid = Y(L + R);
251 // 0到mid-1建模
252
253 build_G(mid);
254 if (SAT(mid))
255 {
256 if (mid > ans) ans = mid;
257 L = mid + 1 ;
258 }
259 else R = mid;
260 }
261
262 printf( " %d\n " ,ans);
263 }
264 return 0 ;
265 }
2 门是按顺序打开的,这点非常重要。
3
4 2SAT,建图,判断有有解
5 关于限制条件,对于key pair.有关系 a and b = 0,最多只能用1个,a1b0,a0b1,a0b0
6 对于门上的key pair,有关系 a or b = 1,只要有一个是1就行,a1b1 a1b0 a0b1
7 关系转化为边,可参考3678
8
9 可用二分加速
10 */
11
12 // include file
13 #include < cstdio >
14 #include < cstdlib >
15 #include < cstring >
16 #include < cmath >
17 #include < cctype >
18 #include < ctime >
19
20 #include < iostream >
21 #include < sstream >
22 #include < fstream >
23 #include < iomanip >
24 #include < bitset >
25 #include < strstream >
26
27 #include < algorithm >
28 #include < string >
29 #include < vector >
30 #include < queue >
31 #include < set >
32 #include < list >
33 #include < functional >
34
35 using namespace std;
36
37 // typedef
38 typedef long long LL;
39 typedef unsigned long long ULL;
40
41 //
42 #define read freopen("in.txt","r",stdin)
43 #define write freopen("out.txt","w",stdout)
44 #define FORi(a,b) for(int i=(a);i<(b);i++)
45 #define FORj(a,b) for(int j=(a);j<(b);j++)
46
47 #define FF(i,a) for(int i=0;i<(a);i+++)
48 #define FFD(i,a) for(int i=(a)-1;i>=0;i--)
49 #define Z(a) (a<<1)
50 #define Y(a) (a>>1)
51
52 const double eps = 1e - 11 ;
53 const double Pi = acos( - 1.0 );
54
55 template < class T > inline T sqr(T a){ return a * a;}
56 template < class T > inline T TMAX(T x,T y)
57 {
58 if (x > y) return x;
59 return y;
60 }
61 template < class T > inline T TMIN(T x,T y)
62 {
63 if (x < y) return x;
64 return y;
65 }
66 template < class T > inline T MMAX(T x,T y,T z)
67 {
68 return TMAX(TMAX(x,y),z);
69 }
70
71
72 // code begin
73 #define MAXN 5010
74
75 struct node
76 {
77 int a,b;
78 };
79
80 node key[MAXN];
81 node door[MAXN];
82
83 vector < int > G[MAXN];
84
85 int scc;
86 int cnt;
87 int used[MAXN];
88 int stk1[MAXN],top1;
89 int stk2[MAXN],top2;
90 int isin[MAXN];
91 int dfn[MAXN];
92 int low[MAXN];
93 int id[MAXN];
94 int N,M;
95
96 void gabow_scc( int i)
97 {
98 used[i] = true ;
99 stk1[top1 ++ ] = i;
100 stk2[top2 ++ ] = i;
101 dfn[i] = cnt ++ ;
102 isin[i] = true ;
103
104 FORj( 0 ,G[i].size() )
105 {
106 if ( ! used[ G[i][j] ])
107 {
108 gabow_scc(G[i][j]);
109 }
110 else if (isin[G[i][j]])
111 {
112 while (dfn[stk2[top2 - 1 ]] > dfn[G[i][j]])
113 top2 -- ;
114 }
115 }
116
117 if (i == stk2[top2 - 1 ])
118 {
119 top2 -- ;
120 int w;
121 do
122 {
123 w = stk1[ -- top1];
124 isin[w] = false ;
125 id[w] = scc;
126 } while (w != i);
127
128 scc ++ ;
129 }
130 }
131
132 void tarjan_scc( int i)
133 {
134 used[i] = true ;
135 stk1[top1 ++ ] = i;
136 dfn[i] = cnt;
137 low[i] = cnt;
138 cnt ++ ;
139 isin[i] = true ;
140
141 FORj( 0 ,G[i].size())
142 {
143 if ( ! used[ G[i][j] ])
144 {
145 tarjan_scc(G[i][j]);
146 low[i] = TMIN(low[i],low[G[i][j]]);
147 }
148 else if (isin[G[i][j]])
149 {
150 low[i] = TMIN(low[i],dfn[G[i][j]]);
151 }
152 }
153
154 if (dfn[i] == low[i])
155 {
156 int w;
157 do
158 {
159 w = stk1[ -- top1];
160 isin[w] = false ;
161 id[w] = scc;
162 } while (w != i);
163 scc ++ ;
164 }
165 }
166
167 void build_G( int sz)
168 {
169 FORi( 0 ,N * 4 )
170 {
171 G[i].clear();
172 }
173 int a,b;
174 FORi( 0 ,N)
175 {
176 // a and b = 0
177 a = key[i].a;
178 b = key[i].b;
179 G[ 2 * a + 1 ].push_back( 2 * b);
180 G[ 2 * b + 1 ].push_back( 2 * a);
181 }
182 FORi( 0 ,sz)
183 {
184 // a or b = 1
185 a = door[i].a;
186 b = door[i].b;
187 G[ 2 * a].push_back( 2 * b + 1 );
188 // G[2*b+1].push_back(2*a);
189 G[ 2 * b].push_back( 2 * a + 1 );
190 // G[2*a+1].push_back(2*b);
191 }
192 }
193
194 bool SAT( int mid)
195 {
196 if (mid == 0 ) return true ;
197 memset(used, 0 , sizeof (used));
198 memset(id, 0 , sizeof (id));
199 top1 = top2 = 0 ;
200 cnt = 1 ;
201 scc = 1 ;
202 memset(isin, 0 , sizeof (isin));
203 memset(dfn, 0 , sizeof (dfn));
204 memset(low, 0 , sizeof (low));
205 FORi( 0 ,N * 4 )
206 {
207 if ( ! used[i])
208 {
209 // gabow_scc(i);
210 tarjan_scc(i);
211 }
212 }
213
214 FORi( 0 ,N * 2 )
215 {
216 if (id[ 2 * i] == id[ 2 * i + 1 ])
217 return false ;
218 }
219 return true ;
220 }
221
222 int main()
223 {
224 read;
225 write;
226 while (scanf( " %d %d " , & N, & M) !=- 1 )
227 {
228 if (N + M == 0 ) break ;
229
230 int a,b;
231 FORi( 0 ,N)
232 {
233 scanf( " %d %d " , & a, & b);
234 key[i].a = a;
235 key[i].b = b;
236 }
237
238 FORi( 0 ,M)
239 {
240 scanf( " %d %d " , & a, & b);
241 door[i].a = a;
242 door[i].b = b;
243 }
244
245 // 0..M
246 int L = 0 ,R = M + 1 ,ans = 0 ;
247
248 while (L < R)
249 {
250 int mid = Y(L + R);
251 // 0到mid-1建模
252
253 build_G(mid);
254 if (SAT(mid))
255 {
256 if (mid > ans) ans = mid;
257 L = mid + 1 ;
258 }
259 else R = mid;
260 }
261
262 printf( " %d\n " ,ans);
263 }
264 return 0 ;
265 }