UVALive 3211 Now or Later (2-SAT)

题目的要求一个最小值最大,二分即可,但是怎么判断呢?

飞机早或者晚两种状态,可以用一个布尔变量表示,假设当前猜测为m,那么根据题意,

如果x和y所对应的时间冲突那么就是¬(xΛy)化成或的形式(¬x)V(¬y),就可以套用twoSAT了。

关于2-SAT,简单理解是,把逻辑推导变成一条有向边,然后跑图判断一下。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 2005;

#define PB push_back
struct TwoSAT
{
    int n,M;
    vector<int> G[maxn*2];
    bool vis[maxn*2];
    int S[maxn*2], c;

    void init(int n)
    {
        this->n = n;
        M = n<<1;
        for(int i = 0; i < M; i++) G[i].clear();
        memset(vis,0,sizeof(vis));
    }

    bool dfs(int x)
    {
        if(vis[x^1]) return false;
        if(vis[x]) return true;
        vis[x] = true;
        S[c++] = x;
        for(int i = 0; i < (int)G[x].size(); i++){
            if(!dfs(G[x][i])) return false;
        }
        return true;

    }

    void add_clause(int x,int xv,int y,int yv)// xv or yv
    {
        x = x<<1|xv;
        y = y<<1|yv;
        G[x^1].PB(y);
        G[y^1].PB(x);
    }

    bool solve()
    {
        for(int i = 0; i < M; i+=2){
            if(!vis[i] && !vis[i+1]){
                c = 0;
                if(!dfs(i)){
                    while(c>0) vis[S[--c]] = false;
                    if(!dfs(i+1)) return false;
                }
            }
        }
        return true;
    }
}solver;

int T[maxn][2];

bool ok(int m,int n)
{
    solver.init(n);
    for(int i = 0; i < n; i++){
        for(int xv = 0; xv < 2; xv++){
            for(int j = i+1; j < n; j++){
                for(int yv = 0; yv < 2; yv++){
                    if(abs(T[i][xv]-T[j][yv])<m){
                        solver.add_clause(i,xv^1,j,yv^1);
                    }
                }
            }
        }
    }
    return solver.solve();
}

int main()
{
    //freopen("in.txt","r",stdin);
    int n;
    while(~scanf("%d",&n)){
        int l = 0, r = 0;
        for(int i = 0; i < n; i++){
            scanf("%d%d",T[i],T[i]+1);
            r = max(r,max(T[i][0],T[i][1]));
        }
        int mid;
        for( ; l < r; ok(mid,n)?l = mid:r = mid-1) mid = (l+r+1)>>1;
        printf("%d
",l);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jerryRey/p/4777434.html