// 题目来源:POJ 2749 // 题目大意:有两点坐标已知,现要在坐标系上各点与两点之一建立路径,已知某些点不能建立在同一个点上,有些点必须建立在同一个点上,求最小曼哈顿距离 // 解决方法:枚举最大值,然后用2-sat判断可行性 #include <cstdio> #include <cstdlib> #include <string> #define o 10000 #define _ 1000000 #define oo 100000000 using namespace std; void link( int, int ); bool check( int ); void tarjan( int ); int next[_], g[_], a[_], b[_], c[_], d[_]; int h[o], code[o], dfn[o], low[o], stack[o], x[o], y[o]; int n, m, sx1, sy1, sx2, sy2, t, top, cnt, index, dis, sa, sb; bool ins[o]; int main( ) { freopen( "2749.in", "r", stdin ); freopen( "2749.out", "w", stdout ); scanf( "%d%d%d%d%d%d%d", &n, &sa, &sb, &sx1, &sy1, &sx2, &sy2 ); dis = abs( sx1 -sx2 ) + abs( sy1 - sy2 ); for( int i = 1; i <= n; i++ ) scanf( "%d%d", &x[i], &y[i] ); for( int i = 1; i <= sa; i++ ) scanf( "%d%d", &a[i], &b[i] ); for( int i = 1; i <= sb; i++ ) scanf( "%d%d", &c[i], &d[i] ); int left = 0, right = oo, mid = ( left + right ) / 2; while( left != right ) { if( check( mid ) ) right = mid; else left = mid + 1; mid = ( left + right ) / 2; } if( left == oo ) printf( "-1" ); else printf( "%d", left ); return 0; } void link( int aa, int bb ) { next[++t] = h[aa]; h[aa] = t; g[t] = bb; } bool check( int limit ) { memset( next, 0, sizeof( next ) ); memset( h, 0, sizeof( h ) ); memset( dfn, 0, sizeof( dfn ) ); memset( low, 0, sizeof( low ) ); memset( code, 0, sizeof( code ) ); t = index = cnt = 0; for( int i = 1; i <= sa; i++ ) { link( a[i], b[i]+n ); link( b[i], a[i]+n ); link( a[i]+n, b[i] ); link( b[i]+n, a[i] ); } for( int i = 1; i <= sb; i++ ) { link( c[i], d[i] ); link( d[i], c[i] ); link( c[i]+n, d[i]+n ); link( d[i]+n, c[i]+n ); } for( int i = 1; i <= n; i++ ) for( int j = i + 1; j <= n; j++ ) { if( abs( x[i]-sx1 )+abs( x[j]-sx1 )+abs( y[i]-sy1 )+abs( y[j]-sy1 ) > limit ) { link( i, j+n ); link( j, i+n ); } if( abs( x[i]-sx1 )+abs( x[j]-sx2 )+abs( y[i]-sy1 )+abs( y[j]-sy2 )+dis > limit ) { link( i, j ); link( j+n, i+n ); } if( abs( x[i]-sx2 )+abs( x[j]-sx1 )+abs( y[i]-sy2 )+abs( y[j]-sy1 )+dis > limit ) { link( i+n, j+n ); link( j, i ); } if( abs( x[i]-sx2 )+abs( x[j]-sx2 )+abs( y[i]-sy2 )+abs( y[j]-sy2 ) > limit ) { link( i+n, j ); link( j+n, i ); } } for( int i = 1; i <= 2*n; i++ ) if( !dfn[i] ) tarjan( i ); for( int i = 1; i <= n; i++ ) if( code[i] == code[i+n] ) return 0; return 1; } void tarjan( int i ) { int j; dfn[i] = low[i] = ++index; stack[++top] = i; ins[i] = true; for( int k = h[i]; k; k = next[k] ) { j = g[k]; if( !dfn[j] ) { tarjan( j ); if( low[j] < low[i] ) low[i] = low[j]; } else if( ins[j] && dfn[j] < low[i] ) low[i] = dfn[j]; } if( dfn[i] == low[i] ) { cnt++; do { j = stack[top--]; code[j] = cnt; ins[j] = false; } while( i != j ); } }