hdu 3622 二分+2-sat

算是比较经典的题目了,精度要适当高一些不然会WA。

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <cstdio>
  5 #include <cmath>
  6 using namespace std;
  7 
  8 const double eps = 1e-5;
  9 const int N = 200;
 10 const int M = 500000;
 11 double dis[N][N];
 12 int head[N];
 13 int s[N];
 14 bool mark[N];
 15 int n, e, c;
 16 
 17 struct Edge
 18 {
 19     int v, next;
 20 } edge[M];
 21 
 22 void addEdge( int u, int v )
 23 {
 24     edge[e].v = v;
 25     edge[e].next = head[u];
 26     head[u] = e++;
 27 }
 28 
 29 void init()
 30 {
 31     e = 0;
 32     memset( head, -1, sizeof(head) );
 33 }
 34 
 35 bool dfs( int u )
 36 {
 37     if ( mark[u ^ 1] ) return false;
 38     if ( mark[u] ) return true;
 39     mark[u] = true;
 40     s[c++] = u;
 41     for ( int i = head[u]; i != -1; i = edge[i].next )
 42     {
 43         int v = edge[i].v;
 44         if ( !dfs(v) ) return false;
 45     }
 46     return true;
 47 }
 48 
 49 bool solve()
 50 {
 51     memset( mark, false, sizeof(mark) );
 52     for ( int i = 0; i < n; i += 2 )
 53     {
 54         if ( !mark[i] && !mark[i + 1] )
 55         {
 56             c = 0;
 57             if ( !dfs(i) )
 58             {
 59                 while ( c )
 60                 {
 61                     c--;
 62                     mark[s[c]] = false;
 63                 }
 64                 if ( !dfs( i + 1 ) ) return false;
 65             }
 66         }
 67     }
 68     return true;
 69 }
 70 
 71 struct Point 
 72 {
 73     int x, y;
 74 } p[N];
 75 
 76 double cal( Point a, Point b )
 77 {
 78     return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) );
 79 }
 80 
 81 int main ()
 82 {
 83     while ( scanf("%d", &n) != EOF )
 84     {
 85         n = n << 1;
 86         for ( int i = 0; i < n; i++ )
 87         {
 88             scanf("%d%d", &p[i].x, &p[i].y);
 89         }
 90         for ( int i = 0; i < n; i++ )
 91         {
 92             for ( int j = i + 1; j < n; j++ )
 93             {
 94                 dis[i][j] = cal( p[i], p[j] );
 95             }
 96         }
 97         double lb = 0, ub = 1e8;
 98         while ( lb + eps < ub )
 99         {
100             init();
101             double mid = ( lb + ub ) / 2.0;
102             for ( int i = 0; i < n; i++ )
103             {
104                 for ( int j = i + 1; j < n; j++ )
105                 {
106                     if ( ( i ^ 1 ) == j ) continue;
107                     if ( 2.0 * mid > eps + dis[i][j] )
108                     {
109                         addEdge( i, j ^ 1 );
110                         addEdge( j, i ^ 1 );
111                     }
112                 }
113             }
114             if ( solve() )
115             {
116                 lb = mid;
117             }
118             else
119             {
120                 ub = mid - eps;
121             }
122         }
123         printf("%.2lf\n", lb);
124     }
125     return 0;
126 }

 

posted @ 2015-08-23 13:25  hxy_has_been_used  阅读(121)  评论(0编辑  收藏  举报