您的位置:首页 > 其它

UVAlive3211 Now or later(2-SAT)

2015-12-18 09:04 357 查看
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=33799

【思路】

2-SAT。

二分安全间隔x,先到为1后到为0,则唯一的限制即两个不同的时间a b如果其间隔小于x则不能满足(a=1 and b=1),即满足 (a or b)=1,如果满足所有的约束条件则x可行。

时间复杂度为O(logt*n^2)。

【代码】

#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int maxn = 2000+10;

struct TwoSAT {
int n;
vector<int> G[maxn*2];
bool mark[maxn*2];
int S[maxn*2],c;

void init(int n) {
this->n=n;
for(int i=0;i<n*2;i++) G[i].clear();
memset(mark,0,sizeof(mark));
}
void addc(int x,int xval,int y,int yval) {
x=x*2+xval;
y=y*2+yval;
G[x^1].push_back(y);
G[y^1].push_back(x);
}
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;
}
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;
}
}ts;

int n;
int t[maxn][2];

bool can(int M) {
ts.init(n);
for(int i=0;i<n;i++)  for(int a=0;a<2;a++)
for(int j=i+1;j<n;j++)  for(int b=0;b<2;b++)
if(abs(t[i][a]-t[j][b])<M) ts.addc(i,a^1,j,b^1);
return ts.solve();
}

int main() {
while(scanf("%d",&n)==1) {
int L=0,R=0;
for(int i=0;i<n;i++) {
scanf("%d%d",&t[i][0],&t[i][1]);
R=max(R,t[i][1]);
}
while(L<R) {
int M=L+(R-L+1)/2;
if(can(M)) L=M; else R=M-1;
}
printf("%d\n",L);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: