UVALive - 3211 Now or later (二分+2SAT)

题目链接

题意:有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\n",bi(0,(int)1e7));
59     }
60     return 0;
61 }

 

posted @ 2019-01-18 09:43  jrltx  阅读(166)  评论(0编辑  收藏  举报