UVALive - 3211 (2-SAT + 二分)
Posted luowentao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVALive - 3211 (2-SAT + 二分)相关的知识,希望对你有一定的参考价值。
layout: post
title: 训练指南 UVALive - 3211 (2-SAT + 二分)
author: "luowentaoaa"
catalog: true
mathjax: true
tags:
- 2-SAT
- 图论
- 训练指南
Now or later
题意
n架飞机,每架可选择两个着落时间。安排一个着陆时间表,使得着陆间隔的最小值最大
题解
二分查找最大值P,每次都用2—SAT判断是否可行。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
struct TwoSAT{
int n;
vector<int> G[maxn*2];
bool mark[maxn*2];
int S[maxn*2],c;
bool dfs(int x){
if(mark[x^1])return false;
if(mark[x])return true;
mark[x]=true;
S[c++]=x;
for(int i=0;i<G[x].size();i++)
if(!dfs(G[x][i]))return false;
return true;
}
void init(int n){
this->n=n;
for(int i=0;i<n*2;i++)G[i].clear();
memset(mark,0,sizeof(mark));
}
/// x=xval or y= yval;
void add_caluse(int x,int xval,int y,int yval){
x=x*2+xval;
y=y*2+yval;
G[x^1].push_back(y);///如果x为真 那么y必须为假;
G[y^1].push_back(x);///如果y为真 那么x必须为假;
}
bool solve(){
for(int i=0;i<n*2;i+=2)
if(!mark[i]&&!mark[i+1]){
c=0;
if(!dfs(i)){
while(c>0)mark[S[--c]]=false;
if(!dfs(i+1))return false;
}
}
return true;
}
};
int n,T[maxn][2];
TwoSAT solver;
bool test(int diff){
solver.init(n);
for(int i=0;i<n;i++)for(int a=0;a<2;a++)
for(int j=i+1;j<n;j++)for(int b=0;b<2;b++)
if(abs(T[i][a]-T[j][b])<diff)solver.add_caluse(i,a^1,j,b^1);
return solver.solve();
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
while(cin>>n&&n){
int L=0,R=0;
for(int i=0;i<n;i++)for(int a=0;a<2;a++){
cin>>T[i][a];
R=max(T[i][a],R);
}
int ans=0;
while(L<=R){
int mid=(L+R)/2;
if(test(mid)){
ans=mid;
L=mid+1;
}
else R=mid-1;
}
cout<<ans<<endl;
}
return 0;
}
以上是关于UVALive - 3211 (2-SAT + 二分)的主要内容,如果未能解决你的问题,请参考以下文章
UVALive 3211 : Now or later (2-SAT)