版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
最小值最大的问题一般都是二分答案,着陆时间为【0,max】,则每次M=(L+R+1)>>1,来进行二分,M为时间间隔。
这道题是图论里面比较经典的2-SAT问题,
下面是白书上的2-SAT模板
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
const int maxn = 2010;
int n,T[maxn][2];
struct TwoSAT {
int n;
vector<int> G[2*maxn];
bool mark[2*maxn];
int c,S[2*maxn]; // 记录标记节点的编号,c为已标记节点数量
void Init(int n) {
this->n = n;
memset(mark,0,sizeof(mark));
c = 0;
memset(S,0,sizeof(S));
for(int i = 0;i < 2*maxn;i++) G[i].clear();
}
// val为0则假,1为真。要求在重新赋值后的x和y中至少满足一个,即xVy
void add_clause(int x,int xval,int y,int yval) {
x = 2*x + xval;
y = 2*y + yval;
G[x^1].push_back(y);
G[y^1].push_back(x);
}
// 标记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 < 2*n;i++) {
if(!dfs(i)) {
while(c) mark[S[--c]] = false;
if(!dfs(i^1)) return false;
}
}
return true;
}
} solver;
bool test(int timediff) {
solver.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]) < timediff) {
solver.add_clause(i,a^1,j,b^1);
}
}
return solver.solve();
}
int main() {
while(scanf("%d",&n) != EOF && n) {
int L = 0,R = 0;
for(int i = 0;i < n;i++) for(int a = 0;a < 2;a++) {
scanf("%d",&T[i][a]);
R = max(R,T[i][a]);
}
while(L < R) {
int M = (L+R+1)>>1;
if(test(M)) L = M;
else R = M - 1;
}
printf("%d\n",R);
}
return 0;
}