码迷,mamicode.com
首页 > 其他好文 > 详细

UVALive - 3211 Now or later (2-SAT)

时间:2015-08-08 13:38:59      阅读:91      评论:0      收藏:0      [点我收藏+]

标签:

题目大意:有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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!