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; }