n架飞机,有早、晚着陆两种方式选择。让你安排着陆方式使得相邻两个着陆时间间隔的最小值尽量大。求该最大值。
建图:
每架飞机i的两个着陆时间视为两个点Ai、Ai+1
设最后答案是T,那么当对于两架飞机,若Ai-Aj <T,说明该两个着陆时间不能同时选择,选择了Ai就得选Aj+1。因此,Ai->Aj+1连一条边
二分答案,再按照上面方式建图求解即可。时间复杂度为O(n^2logT)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
#include<vector>
using namespace std;
#define maxn 4005
#define maxm 32000005
struct Edge{
int to,next;
}edge[maxm];
int cnt,head[maxn],S[maxn],top;
bool vis[maxn];
inline void add(int u,int v)
{
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
bool dfs(int u)
{
if(vis[u^1]) return 0;
if(vis[u]) return 1;
vis[u]=1;
S[top++]=u;
for(int i=head[u];~i;i=edge[i].next)
if(!dfs(edge[i].to)) return 0;
return 1;
}
bool solve(int n)
{
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i+=2)
{
if(vis[i]||vis[i^1]) continue;
top=0;
if(!dfs(i))
{
while(top) vis[S[--top]]=0;
if(!dfs(i^1)) return 0;
}
}
return 1;
}
int n,T[maxn][2];
bool test(int Time)
{
cnt=0;
memset(head,-1,sizeof(head));
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])<Time){
add(i*2+a,(2*j+b)^1);
add(j*2+b,(2*i+a)^1);
}
return solve(n+n);
}
int main()
{
while(~scanf("%d",&n)&&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",L);
}
return 0;
}