zoukankan      html  css  js  c++  java
  • ZOJ 3717 Balloon (二分+2-sat)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3717

    2-sat版题

    对半径R进行二分,将二分得到的R用2-sat判,如果2R<dis(i,j),则建边add_and_zero(i,j),然后看是否有解

      1 // #pragma comment(linker, "/STACK:102400000,102400000")
      2 #include <cstdio>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <string>
      6 #include <cmath>
      7 #include <set>
      8 #include <list>
      9 #include <map>
     10 #include <iterator>
     11 #include <cstdlib>
     12 #include <vector>
     13 #include <queue>
     14 #include <stack>
     15 #include <algorithm>
     16 #include <functional>
     17 using namespace std;
     18 typedef long long LL;
     19 #define ROUND(x) round(x)
     20 #define FLOOR(x) floor(x)
     21 #define CEIL(x) ceil(x)
     22 const int maxn = 410;
     23 const int maxm = 410 * 410;
     24 const int inf = 0x3f3f3f3f;
     25 const LL inf64 = 0x3f3f3f3f3f3f3f3fLL;
     26 const double INF = 1e30;
     27 const double eps = 1e-8;
     28 const int P[4] = {0, 0, -1, 1};
     29 const int Q[4] = {1, -1, 0, 0};
     30 const int PP[8] = { -1, -1, -1, 0, 0, 1, 1, 1};
     31 const int QQ[8] = { -1, 0, 1, -1, 1, -1, 0, 1};
     32 /**
     33 *2-SAT模板: 按字典序排列结果
     34 *输入:按照法则添加边(参数为2*i或者2*i+1)
     35 *运行:先init(n),再add(),再solve()
     36 *注意:add(2*i,2*j)才行
     37 *输出:vis[](1表示选中),solve()(是否有解)
     38 */
     39 // const int maxn = 0;
     40 // const int maxm = 0;
     41 struct Edge
     42 {
     43     int u, v;
     44     int next;
     45 };
     46 struct TwoSAT
     47 {
     48     int n, en;
     49     Edge edge[maxm];
     50     int head[maxn];
     51     int vis[maxn], S[maxn];
     52     int cnt;
     53 
     54     void init(int _n = 0)
     55     {
     56         n = _n;
     57         memset(head, -1, sizeof(head));
     58         en = 0;
     59         memset(vis, 0, sizeof(vis));
     60     }
     61 
     62     void addse(int u, int v)
     63     {
     64         edge[en].u = u;
     65         edge[en].v = v;
     66         edge[en].next = head[u];
     67         head[u] = en++;
     68     }
     69 
     70     bool dfs(int u)
     71     {
     72         if (vis[u ^ 1])return 0;
     73         if (vis[u])return 1;
     74         vis[u] = 1;
     75         S[cnt++] = u;
     76         for (int i = head[u]; i != -1; i = edge[i].next)
     77         {
     78             if (!dfs(edge[i].v))return 0;
     79         }
     80         return 1;
     81     }
     82 
     83     bool solve()
     84     {
     85         for (int i = 0; i < 2 * n; i += 2)
     86         {
     87             if (vis[i] || vis[i ^ 1])continue;
     88             cnt = 0;
     89             if (!dfs(i))
     90             {
     91                 while (cnt)vis[S[--cnt]] = 0;
     92                 if (!dfs(i ^ 1))return 0;
     93             }
     94         }
     95         return 1;
     96     }
     97 
     98     /// x AND y = 1
     99     void add_and_one(int x, int y)
    100     {
    101         addse(x ^ 1, y);
    102         addse(y ^ 1, x);
    103         addse(x, y);
    104         addse(y ^ 1, x ^ 1);
    105         addse(y, x);
    106         addse(x ^ 1, y ^ 1);
    107     }
    108 
    109     /// x AND y = 0
    110     void add_and_zero(int x, int y)
    111     {
    112         addse(x, y ^ 1);
    113         addse(y, x ^ 1);
    114     }
    115 
    116     /// x OR y = 1
    117     void add_or_one(int x, int y)
    118     {
    119         addse(x ^ 1, y);
    120         addse(y ^ 1, x);
    121     }
    122 
    123     /// x OR y = 0
    124     void add_or_zero(int x, int y)
    125     {
    126         addse(x, y ^ 1);
    127         addse(y, x ^ 1);
    128         addse(x, y);
    129         addse(y ^ 1, x ^ 1);
    130         addse(x ^ 1, y ^ 1);
    131         addse(y, x);
    132     }
    133 
    134     /// x XOR y = 1
    135     void add_xor_one(int x, int y)
    136     {
    137         addse(x ^ 1, y);
    138         addse(y ^ 1, x);
    139         addse(x, y ^ 1);
    140         addse(y, x ^ 1);
    141     }
    142 
    143     /// x XOR y = 0
    144     void add_xor_zero(int x, int y)
    145     {
    146         addse(x ^ 1, y ^ 1);
    147         addse(y, x);
    148         addse(x, y);
    149         addse(y ^ 1, x ^ 1);
    150     }
    151 
    152     /// x -> y
    153     void add_to(int x, int y)
    154     {
    155         addse(x, y);
    156         addse(y ^ 1, x ^ 1);
    157     }
    158 } sat;
    159 
    160 int n;
    161 struct Node
    162 {
    163     int x, y, z;
    164     Node(int _x = -1, int _y = -1, int _z = -1): x(_x), y(_y), z(_z) {}
    165 } node[maxn];
    166 void init()
    167 {
    168     //
    169 }
    170 void input()
    171 {
    172     for (int i = 0; i < 2 * n; i++)
    173     {
    174         scanf("%d%d%d", &node[i].x, &node[i].y, &node[i].z);
    175     }
    176 }
    177 void debug()
    178 {
    179     //
    180 }
    181 double dis(int a, int b)
    182 {
    183     return sqrt((node[a].x - node[b].x) * (node[a].x - node[b].x) + (node[a].y - node[b].y) * (node[a].y - node[b].y) + (node[a].z - node[b].z) * (node[a].z - node[b].z));
    184 }
    185 bool test(double r)
    186 {
    187     sat.init(n);
    188     // for (int i = 0; i < n; i++)
    189     // {
    190     //     sat.add_xor_one(2 * i, 2 * i + 1);
    191     // }
    192     for (int i = 0; i < 2 * n; i++)
    193     {
    194         for (int j = i + 1; j < 2 * n; j++)
    195         {
    196             if (2 * r > dis(i, j))
    197                 sat.add_and_zero(i, j);
    198         }
    199     }
    200     return sat.solve();
    201 }
    202 void solve()
    203 {
    204     double L = 0, R = 20000;
    205     while (L + eps < R)
    206     {
    207         double M = (L + R) / 2;
    208         if (test(M)) L = M;
    209         else R = M;
    210     }
    211     printf("%f
    ", L);
    212 }
    213 void output()
    214 {
    215     //
    216 }
    217 int main()
    218 {
    219     // std::ios_base::sync_with_stdio(false);
    220 // #ifndef ONLINE_JUDGE
    221 //     freopen("in.cpp", "r", stdin);
    222 // #endif
    223 
    224     while (~scanf("%d", &n))
    225     {
    226         init();
    227         input();
    228         solve();
    229         output();
    230     }
    231     return 0;
    232 }
    View Code
  • 相关阅读:
    树状数组
    LCA最近公共祖先
    ordered_set
    马拉车算法
    数论
    图论
    其他
    线段树
    序列自动机
    优先队列
  • 原文地址:https://www.cnblogs.com/xysmlx/p/3870002.html
Copyright © 2011-2022 走看看