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;
}
时间: 2024-10-09 02:23:45

UvaLive--3211--Now or later【2-SAT+二分答案】的相关文章

UVALive 3211 Now or later(2-SAT,二分,Kosaraju)

题意:有n个飞机要降落,每机都可以在两个时间点上选择降落.但是两机的降落时间间隔太小会影响安全性,所以,要求两机的降落时间应该达到最大,当然也不能冲突了.问最大的时间间隔是多少?(其实问的是max(每种方案中两机间的最小间隔) ) 思路: 用Kosaraju算法也是可以过的,而且代码也比较少,那就用此法解决了. 主要的步骤是: 二分穷举每个时间间隔,对于每个间隔,建反向图,对图进行DFS着色看是否有冲突,无冲突的话证明此间隔是可以实现的.要找一个可以实现的,且间隔最大的. 1 #include

UVALive - 3211 (2-SAT + 二分)

layout: post title: 训练指南 UVALive - 3211 (2-SAT + 二分) author: "luowentaoaa" catalog: true mathjax: true tags: - 2-SAT - 图论 - 训练指南 Now or later UVALive - 3211 题意 n架飞机,每架可选择两个着落时间.安排一个着陆时间表,使得着陆间隔的最小值最大 题解 二分查找最大值P,每次都用2-SAT判断是否可行. #include<bits

two-sat hdu3062 UVALive 3211

2-sat就是给定形如 x=xval or y=yval的若干约数,求是否存在全部满足. 这是一种dfs的算法,参考大白书 hdu3062 基本上是模板题吧,xval和yval都告诉你了. #include<bits/stdc++.h> using namespace std; const int N=(int)2e3+10; int n,m; int mark[N],s[N],top=0; vector<int> g[N]; bool dfs(int x) { if(mark[x

UVALive - 3211 - Now or later(图论——2-SAT)

Problem   UVALive - 3211 - Now or later Time Limit: 9000 mSec Problem Description Input Output Sample Input 10 44 156 153 182 48 109 160 201 55 186 54 207 55 165 17 58 132 160 87 197 Sample Output 10 题解:2-SAT问题板子题,这个问题主要是理论难度比较大,有了结论之后代码很容易,有专门的论文阐释算

Codeforces 772A Voltage Keepsake - 二分答案

You have n devices that you want to use simultaneously. The i-th device uses ai units of power per second. This usage is continuous. That is, in λ seconds, the device will use λ·ai units of power. The i-th device currently has bi units of power store

HDU3081Marriage Match II(二分答案+并查集+最大流SAP)经典

Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2507    Accepted Submission(s): 856 Problem Description Presumably, you all have known the question of stable marriage match. A

Codeforce 371C Hamburgers (二分答案)

题目链接 Hamburgers 二分答案,贪心判断即可. 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define REP(i,n) for(int i(0); i < (n); ++i) 6 #define LL long long 7 8 char str[1010]; 9 LL len; 10 LL b, c, s, nb, nc, ns, pb, pc, ps; 11 LL money; 12 13 bool

POJ 3080 Blue Jeans(后缀数组+二分答案)

[题目链接] http://poj.org/problem?id=3080 [题目大意] 求k个串的最长公共子串,如果存在多个则输出字典序最小,如果长度小于3则判断查找失败. [题解] 将所有字符串通过拼接符拼成一个串,做一遍后缀数组,二分答案,对于二分所得值,将h数组大于这个值的相邻元素分为一组,判断组内元素是否覆盖全字典,是则答案成立,对于答案扫描sa,输出第一个扫描到的子串即可. [代码] #include <cstdio> #include <cstring> #inclu

【二分答案+智障的字符串hash】BZOJ2946-[Poi2000]公共串(Ranklist倒一达成!!!!!)【含hash知识点】

[题目大意] 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. [字符串hash的小笔记] hash[i]=(hash[i-1]*p+idx(s[i]))%mod,idx为映射值,一般a..z映射1..26: 习惯上,p取一个6到8位的素数即可,mod一般取大素数 1e9+7(1000000007)或1e9+9(1000000009). hash[i]=(hash[i-1]*p+idx(s[i]))%mod 表示第 i 个前缀的hash值,是一个hash的前缀和,那么,要求S[l…r]

IndiaHacks 2016 - Online Edition (Div. 1 + Div. 2) 二分答案 + 网络流

这道题的意思是给你一个有向图, 每条边上有一个最大载重量, 现在有x头牛要从顶点1走向顶点n, 每头牛要载的重量都是一样的, 问你最多能载多少的重量? 可以二分答案, 算出每头牛的载重, 然后修改边权, 跑一次最大流即可判断当前答案是否正确, 二分答案即可, 注意由于原始边权/每头牛的载重量可能会很大, 因此我们在修改边权时应该注意这一点,将边权的最大值控制在1000000之内, 防止溢出, 代码如下: #include <bits/stdc++.h> using namespace std;