白书上的例题。
每种航班可以选择两种时间降落,如果想任意航班降落时间差的最小值最大,应该如何安排?
二分时间,如果两个时间只差小于当前枚举的时间,说明这条边不可选,可以根据2sat的方法构图。
然后判断安排方案是否合法即可。
召唤代码君:
#include <iostream> #include <cstdio> #include <cstring> #define maxn 5555 #define maxm 26666666 using namespace std; int to[maxm],next[maxm],first[maxn],edge; int t[maxn],Q[maxn],top=0; int n,m; bool mark[maxn]; int abs(int x) { return x>=0?x:-x; } void addedge(int U,int V) { edge++; to[edge]=V,next[edge]=first[U],first[U]=edge; } bool dfs(int cur) { if (mark[cur^1]) return false; if (mark[cur]) return true; Q[++top]=cur,mark[cur]=true; for (int i=first[cur]; i!=-1; i=next[i]) if (!dfs(to[i])) return false; return true; } bool check(int x) { edge=-1; for (int i=2; i<=n+n+1; i++) first[i]=-1,mark[i]=false; for (int i=2; i<=n+n+1; i++) for (int j=(i|1)+1; j<=n+n+1; j++) if (abs(t[i]-t[j])<x) addedge(i,j^1),addedge(j,i^1); for (int i=2; i<=n+n; i+=2) { if (mark[i] || mark[i+1]) continue; top=0; if (!dfs(i)) { while (top) mark[Q[top--]]=false; if (!dfs(i+1)) return false; } } return true; } int main() { while (scanf("%d",&n)!=EOF) { for (int i=1; i<=n; i++) scanf("%d%d",&t[i+i],&t[i+i+1]); int l=0,r=10000000,mid; while (l<r) { mid=(l+r+1)>>1; if (check(mid)) l=mid; else r=mid-1; } printf("%d ",l); } return 0; }