UVALive3211 Now or later --- 2-SAT问题+二分答案

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/lmhlmh_/article/details/102170616

最小值最大的问题一般都是二分答案,着陆时间为【0,max】,则每次M=(L+R+1)>>1,来进行二分,M为时间间隔。

这道题是图论里面比较经典的2-SAT问题,

下面是白书上的2-SAT模板

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
const int maxn = 2010;
int n,T[maxn][2];
struct TwoSAT {
    int n;
    vector<int> G[2*maxn];
    bool mark[2*maxn];
    int c,S[2*maxn]; // 记录标记节点的编号,c为已标记节点数量

    void Init(int n) {
        this->n = n;
        memset(mark,0,sizeof(mark));
        c = 0;
        memset(S,0,sizeof(S));
        for(int i = 0;i < 2*maxn;i++) G[i].clear();
    }
    
    // val为0则假,1为真。要求在重新赋值后的x和y中至少满足一个,即xVy
    void add_clause(int x,int xval,int y,int yval) {
        x = 2*x + xval;
        y = 2*y + yval;
        G[x^1].push_back(y);
        G[y^1].push_back(x);
    }
    
    // 标记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 = 0;i < G[x].size();i++) {
            if(!dfs(G[x][i])) {
                return false;
            }
        }
        return true;
    }

    bool solve() {
        for(int i = 0;i < 2*n;i++) {
            if(!dfs(i)) {
                while(c) mark[S[--c]] = false;
                if(!dfs(i^1)) return false;
            }
        }
        return true;
    }

} solver;


bool test(int timediff) {
    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(T[i][a]-T[j][b]) < timediff) {
            solver.add_clause(i,a^1,j,b^1);
        }
    }
    return solver.solve();
}

int main() {
    while(scanf("%d",&n) != EOF && n) {
        int L = 0,R = 0;
        for(int i = 0;i < n;i++) for(int a = 0;a < 2;a++) {
            scanf("%d",&T[i][a]);
            R = max(R,T[i][a]);
        }
        while(L < R) {
            int M = (L+R+1)>>1;
            if(test(M)) L = M;
            else R = M - 1;
        }
        printf("%d\n",R);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/lmhlmh_/article/details/102170616
now