标签:
题目大意:有n架飞机需要着陆。每架飞机有两种选择,早着陆或者晚着陆,二选其一
现在为了保证飞机的着陆安全,要求两架着陆的飞机的时间间隔的最小值达到最大
解题思路:最小值最大,二分枚举
设第i架飞机选择着陆方式为a,第j架飞机选择着陆的方式为b,枚举的时间间隔为mid
如果abs(plane[i][a] - plane[j][b]) < mid,表明这两架飞机以这样的着陆方式是矛盾的,所以只能二选其一,这样,关系式就推出来了
链式前向星
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 4010
#define M 16000010
struct Edge{
int to, next;
}E[M];
struct TwoSAT {
int n, c, tot;
int S[N], head[N];
bool mark[N];
void init(int n) {
this->n = n;
tot = 0;
memset(head, -1, sizeof(head));
memset(mark, 0, sizeof(mark));
}
void AddEdge(int from, int to) {
E[tot].to = to;
E[tot].next = head[from];
head[from] = tot++;
}
void add_clause(int x, int xval, int y, int yval) {
x = x * 2 + xval;
y = y * 2 + yval;
AddEdge(x ^ 1, y);
AddEdge(y ^ 1, x);
}
bool dfs(int x) {
if (mark[x ^ 1]) return false;
if (mark[x]) return true;
mark[x] = true;
S[c++] = x;
for (int i = head[x]; i != -1; i = E[i].next)
if (!dfs(E[i].to)) return false;
return true;
}
bool solve() {
for (int i = 0; i < 2 * n; i++) {
if (!mark[i] && !mark[i ^ 1]) {
c = 0;
if (!dfs(i)) {
while (c) mark[S[--c]] = false;
if (!dfs(i ^ 1)) return false;
}
}
}
return true;
}
};
TwoSAT solver;
int n;
int plane[N][2];
int L, R;
#include <cstdlib>
bool judge(int mid) {
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(plane[i][a] - plane[j][b]) < mid)
solver.add_clause(i, a ^ 1, j, b ^ 1);
return solver.solve();
}
void solve() {
while (L <= R) {
int mid = (L + R) / 2;
if (judge(mid))
L = mid + 1;
else
R = mid - 1;
}
printf("%d\n", L - 1);
}
void init() {
L = 0; R = -1;
for (int i = 0; i < n; i++)
for (int j = 0; j < 2; j++) {
scanf("%d", &plane[i][j]);
if (R < plane[i][j])
R = plane[i][j];
}
}
int main() {
while (scanf("%d", &n) != EOF && n) {
init();
solve();
}
return 0;
}
vector
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
using namespace std;
#define N 2010
#define INF 0x3f3f3f3f
int n, Max;
int plane[N][2];
struct TwoSAT{
int n;
vector<int> G[N * 2];
bool mark[N * 2];
int S[N * 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 < 2 * n; i++)
G[i].clear();
memset(mark, 0, sizeof(mark));
}
//x == xval or y == yval
void add_clause(int x, int xval, int y, int yval) {
x = x * 2 + xval;
y = y * 2 + yval;
G[x^1].push_back(y);
G[y^1].push_back(x);
}
bool solve() {
for (int i = 0; i < 2 * n; 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;
}
};
TwoSAT solver;
bool test(int mid) {
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(plane[i][a] - plane[j][b]) < mid)
solver.add_clause(i, a ^ 1, j, b ^ 1);
return solver.solve();
}
void solve() {
Max = -INF;
for (int i = 0; i < n; i++)
for (int j = 0; j < 2; j++) {
scanf("%d", &plane[i][j]);
if (Max < plane[i][j])
Max = plane[i][j];
}
int L = 0, R = Max;
while (L <= R) {
int mid = (L + R) / 2;
if (test(mid))
L = mid + 1;
else
R = mid - 1;
}
printf("%d\n", L - 1);
}
int main() {
while (scanf("%d", &n) != EOF && n) {
solve();
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
UVALive - 3211 Now or later (2-SAT)
标签:
原文地址:http://blog.csdn.net/l123012013048/article/details/47356981