标签:
题目的要求一个最小值最大,二分即可,但是怎么判断呢?
飞机早或者晚两种状态,可以用一个布尔变量表示,假设当前猜测为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\n",l); } return 0; }
标签:
原文地址:http://www.cnblogs.com/jerryRey/p/4777434.html