您的位置:首页 > 其它

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

2013-11-02 17:54 489 查看
http://poj.org/problem?id=2296

很好的一道2-SAT题

取上为1,取下为0

两个新规则:

a = 0: 这个等价于加边!a->a

a = 1: 这个等价于加边a->!a

当二者y差值<r时,y大的在上,y小的在下

如果等于r时,取i xor j = 1

如果大于r小于2r,则y大的在下,y小的在上这种情况不能存在(and = 0)

其他情况怎么放都可以

//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<list>
#include<map>
#include<iterator>
#include<cstdlib>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
#include<functional>
using namespace std;
typedef long long LL;
#define ROUND(x) round(x)
#define FLOOR(x) floor(x)
#define CEIL(x) ceil(x)
const int maxn=110;
const int maxm=0;
const int inf=0x3f3f3f3f;
const LL inf64=0x3f3f3f3f3f3f3f3fLL;
const double INF=1e30;
const double eps=1e-6;

/**
*2-SAT模板,Modified Edition of LRJ 按字典序排列结果
*输入:按照法则添加边(参数为2*i或者2*i+1)
*运行:先init(n),再add(),再solve()
*注意:add(2*i,2*j)才行
*输出:mark[](1表示选中),solve()(是否有解)
*/
//const int maxn = 0;
struct TwoSAT
{
int n;
vector<int> G[maxn*2];
bool mark[maxn*2];
int S[maxn*2], c;

bool dfs(int x)
{
if (mark[x^1]) return false;
if (mark[x]) return true;
mark[x] = true;
S[c++] = x;
for (int i = 0; i < G[x].size(); i++)
if (!dfs(G[x][i])) return false;
return true;
}

void init(int n)
{
this->n = n;
for (int i = 0; i < n*2; i++) G[i].clear();
memset(mark, 0, sizeof(mark));
}

/// x AND y = 1
void add_and_one(int x,int y)
{
G[x^1].push_back(y);
G[y^1].push_back(x);
G[x].push_back(y);
G[y^1].push_back(x^1);
G[y].push_back(x);
G[x^1].push_back(y^1);
}

/// x AND y = 0
void add_and_zero(int x,int y)
{
G[x].push_back(y^1);
G[y].push_back(x^1);
}

/// x OR y = 1
void add_or_one(int x,int y)
{
G[x^1].push_back(y);
G[y^1].push_back(x);
}

/// x OR y = 0
void add_or_zero(int x,int y)
{
G[x].push_back(y^1);
G[y].push_back(x^1);
G[x].push_back(y);
G[y^1].push_back(x^1);
G[x^1].push_back(y^1);
G[y].push_back(x);
}

/// x XOR y = 1
void add_xor_one(int x,int y)
{
G[x^1].push_back(y);
G[y^1].push_back(x);
G[x].push_back(y^1);
G[y].push_back(x^1);
}

/// x XOR y = 0
void add_xor_zero(int x,int y)
{
G[x^1].push_back(y^1);
G[y].push_back(x);
G[x].push_back(y);
G[y^1].push_back(x^1);
}

/// x -> y
void add_to(int x,int y)
{
G[x].push_back(y);
G[y^1].push_back(x^1);
}

bool solve()
{
for(int i = 0; i < n*2; i += 2)
if(!mark[i] && !mark[i+1])
{
c = 0;
if(!dfs(i))
{
while(c > 0) mark[S[--c]] = false;
if(!dfs(i+1)) return false;
}
}
return true;
}
} sat;

int n;
struct Node
{
int x,y;
} node[maxn];
void init()
{
//
}
void input()
{
scanf("%d",&n);
for(int i=0; i<n; i++) scanf("%d%d",&node[i].x,&node[i].y);
}
bool test(int r)
{
sat.init(n);
for(int i=0; i<n; i++)
{
for(int j=i+1; j<n; j++)
{
if(abs(node[i].x-node[j].x)>=r||abs(node[i].y-node[j].y)>=2*r) continue;
if(abs(node[i].y-node[j].y)<r)
{
if(node[i].y>node[j].y)
{
sat.G[2*i+1].push_back(2*i);
sat.G[2*j].push_back(2*j+1);
}
else if(node[i].y<node[j].y)
{
sat.G[2*j+1].push_back(2*j);
sat.G[2*i].push_back(2*i+1);
}
else
{
sat.add_xor_one(2*i,2*j);
}
}
else
{
if(node[i].y>node[j].y) sat.add_and_zero(2*i+1,2*j);
else sat.add_and_zero(2*j+1,2*i);
}
}
}
if(sat.solve()) return 1;
return 0;
}
void solve()
{
int L=0,R=inf;
while(L<R)
{
int M=L+(R-L)/2;
if(!test(M)) R=M;
else L=M+1;
}
printf("%d\n",L-1);
}
void output()
{
//
}
int main()
{
//    std::ios_base::sync_with_stdio(false);
//    freopen("in.cpp","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
init();
input();
solve();
output();
}
return 0;
}


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