uvalive 3211 Now or later

算法指南

就是从飞机早着陆还晚着路两种状态可以组合成一个点,类似2--sat把一个点划分成两个点来表示状态,再二分时间,如果小于时间则可以转化成相应的约数条件:“xi或xj为假”这样的条件。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<queue>
 5 #include<stack>
 6 #include<bits/stdc++.h>
 7 using namespace std;
 8 #define LL long long
 9 const int maxn = 2000 + 10;
10 //模板
11 struct TwoSAT {
12     int n;
13     vector<int> G[maxn*2];
14     bool mark[maxn*2];
15     int S[maxn*2], c;
16 
17     bool dfs(int x) {
18         if (mark[x^1]) return false;
19         if (mark[x]) return true;
20         mark[x] = true;
21         S[c++] = x;
22         for (int i = 0; i <(int)G[x].size(); i++)
23             if (!dfs(G[x][i])) return false;
24         return true;
25     }
26 
27     void init(int n) {
28         this->n = n;
29         for (int i = 0; i < n*2; i++) G[i].clear();
30         memset(mark, 0, sizeof(mark));
31     }
32 
33     // x = xval or y = yval
34     void add_clause(int x, int xval, int y, int yval) {
35         x = x * 2 + xval;
36         y = y * 2 + yval;
37         G[x^1].push_back(y);
38         G[y^1].push_back(x);
39     }
40 
41     bool solve() {
42         for(int i = 0; i < n*2; i += 2)
43             if(!mark[i] && !mark[i+1]) {
44                 c = 0;
45                 if(!dfs(i)) {
46                     while(c > 0) mark[S[--c]] = false;
47                     if(!dfs(i+1)) return false;
48                 }
49             }
50         return true;
51     }
52 };
53 
54 TwoSAT solver;
55 
56 int n, T[maxn][2];
57 
58 bool test(int diff) {
59     solver.init(n);
60     for(int i = 0; i < n; i++) for(int a = 0; a < 2; a++)
61             for(int j = i+1; j < n; j++) for(int b = 0; b < 2; b++)
62                     if(abs(T[i][a] - T[j][b]) < diff) //只有小于diff的时候才满足布尔关系,详见算法指南
63                     solver.add_clause(i, a^1, j, b^1);//i,j之间建立边,注意早飞还是晚飞状态
64     return solver.solve();
65 }
66 
67 int main() {
68     while(scanf("%d", &n) == 1 && n) {
69         int L = 0, R = 0;
70         for(int i = 0; i < n; i++) for(int a = 0; a < 2; a++) {
71                 scanf("%d", &T[i][a]);
72                 R = max(R, T[i][a]);
73             }
74             //二分时间,如果大于中间值,则证明还可以增大时间
75         while(L < R) {
76             int M = L + (R-L+1)/2;
77             if(test(M)) L = M;
78             else R = M-1;
79         }
80         printf("%d
", L);
81     }
82     return 0;
83 }
View Code