【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 }
2016-03-25 13:46:05