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

题意:

  有n架飞机需要着陆。每架飞机有两种选择,早着陆或者晚着陆,二选其一。现在为了保证飞机的着陆安全,要求两架着陆的飞机的时间间隔的最小值达到最大。

 

分析:

  最小值最大问题我们想到二分答案。对于猜测值x,判断是否有一种方案使相邻两着陆时间都不小于x。

  如果两架飞机的某着陆时间差小于p,证明不能同时选择。根据这个条件建图,再用2-SAT判断是否有解即可。

 

代码如下:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #define Maxn 2010
 5 #define Maxm 10000010
 6 
 7 int n;
 8 int first[2*Maxn],mark[2*Maxn],s[2*Maxn];
 9 int a[Maxn],b[Maxn];
10 int c,v;
11 
12 struct node
13 {
14     int x,y,next;
15 }t[4*Maxm];int len;
16 
17 int mymax(int x,int y) {return x>y?x:y;}
18 int myabs(int x) {return x<0?-x:x;}
19 
20 void ins(int x,int y)
21 {
22     t[++len].x=x;t[len].y=y;
23     t[len].next=first[x];first[x]=len;
24 }
25 
26 bool dfs(int x)
27 {
28     if(mark[x^1]) return 0;
29     if(mark[x]) return 1;
30     mark[x]=1;
31     s[++c]=x;
32     for(int i=first[x];i;i=t[i].next)
33      if(!dfs(t[i].y)) return 0;
34     return 1;
35 }
36 
37 bool solve()
38 {
39     memset(mark,0,sizeof(mark));
40     for(int i=0;i<n;i++)
41      if(!mark[2*i]&&!mark[2*i+1])
42      {
43          c=0;
44          if(!dfs(2*i))
45          {
46              while(c>0) mark[s[c--]]=0;
47              if(!dfs(2*i+1)) return 0;
48         }
49       }
50       return 1;
51 }
52 
53 bool check(int x)
54 {
55     memset(first,0,sizeof(first));len=0;
56     for(int i=1;i<=n;i++)
57      for(int j=i+1;j<=n;j++)
58      {
59         if(myabs(a[i]-a[j])<x)  {ins((i-1)*2,(j-1)*2+1);     ins((j-1)*2,(i-1)*2+1);}
60          if(myabs(a[i]-b[j])<x) {ins((i-1)*2,(j-1)*2);     ins((j-1)*2+1,(i-1)*2+1);}
61          if(myabs(b[i]-a[j])<x) {ins((i-1)*2+1,(j-1)*2+1);  ins((j-1)*2,(i-1)*2);}
62          if(myabs(b[i]-b[j])<x) {ins((i-1)*2+1,(j-1)*2);      ins((j-1)*2+1,(i-1)*2);}
63      }
64     return solve();
65 }
66 
67 void ffind(int l,int r)
68 {
69     int mid;
70     while(l<r)
71     {
72         mid=(l+r+1)>>1;
73         if(check(mid)) l=mid;
74         else r=mid-1;
75     }
76     printf("%d\n",l);
77 }
78 
79 int main()
80 {
81     while(scanf("%d",&n)!=EOF)
82     {
83         int mx=0;
84         for(int i=1;i<=n;i++)
85         {
86             scanf("%d%d",&a[i],&b[i]);
87             mx=mymax(mx,mymax(a[i],b[i]));
88         }
89         ffind(0,mx);
90     }
91     return 0;
92 }
[LA3211]

 

2016-03-25 13:46:05

posted @ 2016-03-25 13:45  konjak魔芋  阅读(176)  评论(0编辑  收藏  举报