题意:有n架飞机,每架飞机有两个着陆时间点可以选,要求任意两架飞机的着陆时间之差不超过k,求k的最大值。
解法:由于每架飞机都有两个选择,并且必选且只能选其中一个,时间冲突也是发生在两架飞机之间的,因此二分答案,对冲突的时间建边处理,然后跑2SAT即可。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 5 using namespace std; 6 const int N=4000+10; 7 struct E { 8 int v,nxt; 9 } e[N*N]; 10 int n,hd[N],ne; 11 void init() {memset(hd,-1,sizeof hd); ne=0;} 12 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;} 13 14 int dfn[N],low[N],scc[N],sta[N],nscc,nsta,tot; 15 void dfs(int u) { 16 dfn[u]=low[u]=++tot; 17 sta[nsta++]=u; 18 for(int i=hd[u]; ~i; i=e[i].nxt) { 19 int v=e[i].v; 20 if(!dfn[v])dfs(v),low[u]=min(low[u],low[v]); 21 else if(!scc[v])low[u]=min(low[u],dfn[v]); 22 } 23 if(low[u]==dfn[u]) { 24 nscc++; 25 for(; !scc[u]; scc[sta[--nsta]]=nscc); 26 } 27 } 28 void getscc() { 29 memset(dfn,0,sizeof dfn); 30 memset(scc,0,sizeof scc); 31 tot=nscc=nsta=0; 32 for(int i=0; i<n*2; ++i)if(!dfn[i])dfs(i); 33 } 34 35 int x[N],y[N]; 36 int p1(int x) {return x<<1;} 37 int p2(int x) {return x<<1|1;} 38 39 bool ok(int k) { 40 init(); 41 for(int i=0; i<n; ++i) 42 for(int j=i+1; j<n; ++j) { 43 if(abs(x[i]-x[j])<k)addedge(p1(i),p2(j)),addedge(p1(j),p2(i)); 44 if(abs(x[i]-y[j])<k)addedge(p1(i),p1(j)),addedge(p2(j),p2(i)); 45 if(abs(y[i]-x[j])<k)addedge(p2(i),p2(j)),addedge(p1(j),p1(i)); 46 if(abs(y[i]-y[j])<k)addedge(p2(i),p1(j)),addedge(p2(j),p1(i)); 47 } 48 getscc(); 49 for(int i=0; i<n; ++i)if(scc[p1(i)]==scc[p2(i)])return false; 50 return true; 51 } 52 53 int bi(int l,int r) {for(int mid; l<r; mid=(l+r+1)>>1,ok(mid)?l=mid:r=mid-1); return l;} 54 55 int main() { 56 while(scanf("%d",&n)==1) { 57 for(int i=0; i<n; ++i)scanf("%d%d",&x[i],&y[i]); 58 printf("%d ",bi(0,(int)1e7)); 59 } 60 return 0; 61 }