首页 > 代码库 > UvaLive--3211--Now or later【2-SAT+二分答案】

UvaLive--3211--Now or later【2-SAT+二分答案】

链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1212

题意:有n架飞机需要着陆,每架飞机都可以选择“早着陆”或“晚着陆”两种方式,第i架飞机早着陆时间为Ei,晚着陆时间为Li,不得在其他时间着陆。你的任务是为这些飞机安排着陆方式,使得整个着陆计划尽量安全。换言之,如果把所有飞机的实际着陆时间从小到大排序,相邻两个着陆时间间隔的最小值应尽量大。


思路:这是刘汝佳白书上的2-SAT例题,用的书上的模板,思路也按他的写了。

“最小值尽量大”的典型处理方法是二分查找最终答案P。这样原来的问题转换为判定为题“是否存在一个调度方案,使得相邻两个着陆时间差总是不小于P”,而这个问题可以进一步转换为:任意两个着陆时间差总是不小于P。令bool变量xi表示第i架飞机是否早着陆,则唯一的限制就是“时间差小于P的两个着陆时间不能同时满足”。每一组不能同时满足的着陆时间对应于一个子句,则整个约束条件对应于一个2-SAT问题的实例,包含n个变量和n*(n-1)/2个子句。


#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 2010
#define eps 1e-7
#define INF 0x3F3F3F3F      //0x7FFFFFFF
#define LLINF 0x7FFFFFFFFFFFFFFF
#define seed 1313131
#define MOD 1000000007
#define ll long long
#define ull unsigned ll
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

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_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 < 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;
    }
};

TwoSAT fuck;
int n, T[MAXN][2];

bool gao(int diff){
    int i, j;
    fuck.init(n);
    for(i = 0; i < n; i++){
        for(int a = 0; a < 2; a++){
            for(j = i + 1; j < n; j++){
                for(int b = 0; b < 2; b++){
                    if(abs(T[i][a] - T[j][b]) < diff)
                        fuck.add_clause(i, a ^ 1, j, b ^ 1);
                }
            }
        }
    }
    return fuck.solve();
}
int main(){
    int i, j;
    while(scanf("%d", &n) != EOF){
        int l = 0, r = 0;
        for(i = 0; i < n; i++){
            scanf("%d%d", &T[i][0], &T[i][1]);
            int temp = max(T[i][0], T[i][1]);
            r = max(r, temp);
        }
        int ans;
        while(l <= r){
            int mid = (l + r) / 2;
            if(gao(mid)){
                if(!gao(mid + 1)){
                    ans = mid;
                    break;
                }
                else    l = mid + 1;
            }
            else    r = mid - 1;
        }
        printf("%d\n", ans);
    }
    return 0;
}


UvaLive--3211--Now or later【2-SAT+二分答案】