这个类型的题目很典型,就是 二分+2sat
题目:在一个坐标系上,有n个点,每个点贴上标签,标签是正方形的,粘贴的位置要使得点正好在标签的上边中间,或者下边中间,标签之间不能重合,求解,标签的最大边长是多少?
分析:
这道题和前天做的拿到反炸弹的题目很类似,都是用二分查找找最大值,然后一个一个用2-sat判断可行性
这道题的代码,我写得实在太憋屈了,犯了很低级的错误,简直就是一个马虎神。最忌讳的就是知道算法和模板,最后细节出错!以后必须要细心!
代码如下:(邻接链表)
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int N = 220; const int M = 40000+100; const int INF = 80000; struct edge { int to, next; }e1[M], e2[M]; struct point { int x, y; }s[N]; int head1[N], head2[N], T[N], belong[N]; bool v1[N], v2[N]; int t, n, ans; int id1, id2, Bcnt, Tcnt; void add( int u, int v ) { e1[id1].next = head1[u], e1[id1].to = v; head1[u] = id1++; e2[id2].next = head2[v], e2[id2].to = u; head2[v] = id2++; } void dfs( int x ) { v1[x] = 1; for ( int i = head1[x]; i != -1; i = e1[i].next ) if ( !v1[e1[i].to] ) dfs(e1[i].to); T[Tcnt++] = x; } void rdfs( int x ) { v2[x] = true; for ( int i = head2[x]; i != -1; i = e2[i].next ) if ( !v2[e2[i].to] ) rdfs(e2[i].to); belong[x] = Bcnt; } void korasaju() { for ( int i = 0; i < n*2; ++i ) if ( !v1[i] ) dfs(i); for ( int i = Tcnt-1; i >= 0; --i ) if ( !v2[T[i]] ) { rdfs( T[i] ); Bcnt++; } } bool solve() { for ( int i = 0; i < n; ++i ) if ( belong[i*2] == belong[i*2+1] ) return false; return true; } int main() { while ( scanf("%d", &t) != EOF ) { while ( t-- ) { scanf("%d", &n); for ( int i = 0; i < n; ++i ) { int x, y; scanf("%d%d", &s[i].x, &s[i].y); } int left = 0, right = INF, mid; while ( left <= right ) { mid = ( left+right ) / 2; memset(head1, -1, sizeof(head1) ); memset(head2, -1, sizeof(head2) ); memset(v1, 0, sizeof(v1) ); memset(v2, 0, sizeof(v2) ); Tcnt = Bcnt = id1 = id2 = 0; for ( int i = 0; i < n-1; ++i ) for ( int j = i+1; j < n; ++j ) { if ( abs( s[i].x - s[j].x ) >= mid ) continue; if ( s[i].y == s[j].y ) { add(i*2, j*2+1); add(j*2, i*2+1); add(j*2+1, i*2); add(i*2+1, j*2); } else if ( abs( s[i].y - s[j].y ) < mid ) { if ( s[i].y > s[j].y ) { add(2*i+1, 2*i); add(2*j, 2*j+1); } else { add(2*j+1, 2*j); add(i*2, i*2+1); } } else if ( abs( s[i].y - s[j].y ) < mid*2 ) { if ( s[i].y > s[j].y ) { add(i*2+1, j*2+1); add(j*2, i*2); } else { add(j*2+1, i*2+1); add(i*2, j*2); } } } korasaju(); //for ( int i = 0; i < 2*n; ++i ) printf("%d ", belong[i]); //printf("\n"); //printf("%d %d %d %d\n", left, mid, right, solve()); if ( solve() ) left = mid+1, ans = mid; else right = mid-1; } printf("%d\n", ans); } } }
#include <cstdio> #include <vector> #include <algorithm> #include <cstring> using namespace std; const int N = 210; vector < int > adj[N]; //原图 vector < int > radj[N]; //逆图 struct point { int x, y; }s[N]; int T, n; int id[N], cnt, order[N]; bool vis[N]; void init() { for ( int i = 0; i <= n*2; ++i ) { adj[i].clear(); radj[i].clear(); } } void dfs( int x ) { int len = adj[x].size(); vis[x] = 1; for ( int i = 0; i < len; ++i ) if ( !vis[adj[x][i]] ) dfs( adj[x][i] ); order[cnt++] = x; } void rdfs( int x ) { int len = radj[x].size(); vis[x] = 1; id[x] = cnt; for ( int i = 0; i < len; ++i ) if ( !vis[radj[x][i]] ) rdfs( radj[x][i] ); } void kora() { int i; memset( vis, 0, sizeof(vis)); for ( cnt = 0, i = 0; i < 2*n; ++i ) if ( !vis[i] ) dfs( i ); memset( vis, 0, sizeof(vis)); for ( cnt = 0, i = 2*n-1; i >= 0; --i ) if ( !vis[order[i]] ){ cnt++; rdfs( order[i] ); } } bool solve() { for ( int i = 0; i < n; ++i ) if ( id[i*2] == id[i*2+1] ) return false; return true; } int main() { while ( scanf("%d", &T) != EOF ) { while ( T-- ) { scanf("%d", &n); for ( int i = 0; i < n; ++i ) scanf("%d%d", &s[i].x, &s[i].y); int left = 0, right = 80000, mid, ans; while ( left <= right ) { mid = ( left + right ) / 2; init(); for ( int i = 0; i < n; ++i ) for ( int j = i+1; j < n; ++j ) { if ( abs( s[i].x - s[j].x ) >= mid ) continue; if ( abs( s[i].y - s[j].y ) < mid ) { if ( s[i].y == s[j].y ) { adj[i*2].push_back( j*2+1 ); adj[j*2].push_back( i*2+1 ); adj[i*2+1].push_back( j*2 ); adj[j*2+1].push_back( i*2 ); radj[j*2+1].push_back(i*2); radj[i*2+1].push_back(j*2); radj[j*2].push_back(i*2+1); radj[i*2].push_back(j*2+1); } else if ( s[i].y > s[j].y ) { //i上j下 adj[i*2+1].push_back(i*2); adj[j*2].push_back(j*2+1); radj[i*2].push_back(i*2+1); radj[j*2+1].push_back(j*2); } else { adj[j*2+1].push_back(j*2); adj[i*2].push_back(i*2+1); radj[j*2].push_back(j*2+1); radj[i*2+1].push_back(i*2); } } else if ( abs( s[i].y - s[j].y ) < mid*2 ) { if ( s[i].y > s[j].y ) { adj[i*2+1].push_back(j*2+1); adj[j*2].push_back(i*2); radj[i*2].push_back(j*2); radj[j*2+1].push_back(i*2+1); } else { adj[j*2+1].push_back(i*2+1); adj[i*2].push_back(j*2); radj[j*2].push_back(i*2); radj[i*2+1].push_back(j*2+1); } } } kora(); if ( solve() ) ans = mid, left = mid+1; else right= mid-1; } printf("%d\n", ans); } } }