您的位置:首页 > 其它

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

2013-03-23 13:43 330 查看
这个类型的题目很典型,就是 二分+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
;
int head1
, head2
, T
, belong
;
bool v1
, v2
;
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
; //原图
vector < int > radj
; //逆图
struct point {
int x, y;
}s
;
int T, n;
int id
, cnt, order
;
bool vis
;

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: