您的位置:首页 > 其它

UVALive 3211 Now or later(二份答案+2-SAT)

2014-02-25 15:42 344 查看
题目:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1212

题目大意:有n架飞机要降落,可以选择 早着陆 或者 晚着陆 ,给你这n架飞机两种着陆的时刻表,让你安排,使得两架飞机着陆的时间间隔尽可能大,并输出这个时间。

解题思路:要求答案最大,很容易想到二分答案。然后就是判断这个答案可不可行,这只要做一遍2-SAT就行。再看看时限,时间复杂度为O(n*nlogT),过得去。

代码如下:

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

const int MAXN = 2222;

int t[MAXN][2];

struct Two_Sat
{
int n;
vector<int> G[MAXN<<1];
bool mark[MAXN<<1];
int S[MAXN<<1],c;
void init(int n)
{
this->n = n;
for(int i = 0;i < (n<<1);i++)
G[i].clear();
memset(mark,0,sizeof(mark));
}

void add_clause(int x,int x_val,int y,int y_val)
{
x = (x<<1)+x_val;
y = (y<<1)+y_val;
G[x].push_back(y^1);
G[y].push_back(x^1);
}

int dfs(int u)
{
if(mark[u^1]) return 0;
if(mark[u]) return 1;
mark[u] = 1;
S[c++] = u;
for(int i = 0;i < G[u].size();i++)
{
int v = G[u][i];
if(!dfs(v)) return 0;
}
return 1;
}

int solve()
{
for(int i = 0;i < (n<<1);i += 2)
{
if(!mark[i] && !mark[i+1])
{
c = 0;
if(!dfs(i))
{
while(c)
{
mark[S[--c]] = 0;
}
if(!dfs(i+1)) return 0;
}
}
}
return 1;
}
} two;

int check(int mid,int n)
{
two.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]) < mid)
{
two.add_clause(i,a^1,j,b^1);
}
return two.solve();
}

int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i = 0;i < n;i++)
scanf("%d%d",&t[i][0],&t[i][1]);
int l = 0,r = 1e7;
int ans = 0;
while(l <= r)
{
int mid = (l+r)>>1;
if(check(mid,n))
{
ans = mid;
l = mid+1;
}
else r = mid-1;
}
printf("%d\n",ans);
}
return 0;
}

/*
2
1 10
4 14
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: