POJ 2296 Map Labeler ( 2-SAT判定 + 二分查找 )

这个类型的题目很典型,就是 二分+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);
        }
    }
}

代码:(vector边表)

#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);
        }
    }
}



你可能感兴趣的:(POJ 2296 Map Labeler ( 2-SAT判定 + 二分查找 ))