题目大意:
N架飞机需要着陆,每架飞机都有一个早着陆时间和晚着陆时间,安排飞机着陆方式,使得相邻两个着陆时间间隔的最小值最大。
解题思路:
"最小值最大问题”典型的处理方式就是二分查找最终答案P,这样将问题转化为是否存在一个安排方案,使得任意两个相邻着陆时间的间隔都不小于P。
这个问题可以进一步转化为一个2-SAT问题,将两个时间差小于P的点相连,判断是否存在解。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#define LL long long
using namespace std;
const int maxn = 10000 + 10;
class TwoSAT
{
public:
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<=2*n;i++) G[i].clear();
memset(mark,0,sizeof(mark));
}
void AddEdge(int x,int y)
{
G[x^1].push_back(y);
G[y^1].push_back(x);
}
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;
}
};
TwoSAT g;
int n , T[maxn][2];
bool test(int limit)
{
g.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]) < limit)
g.AddEdge(2*i+a,2*j+b);
}
}
}
}
return g.solve();
}
int main()
{
while(scanf("%d",&n)!=EOF && n)
{
int L = 0 , R = 0;
for(int i=0;i<n;i++)
{
for(int j=0;j<2;j++)
{
scanf("%d",&T[i][j]);
R = max(R,T[i][j]);
}
}
while(L < R)
{
int m = L + (R - L + 1) / 2;
if(test(m)) L = m ;
else R = m - 1;
}
printf("%d\n",R);
}
return 0;
}