Hdu--3622(2-SAT,scc缩点)

2014-10-16 22:56:40

思路:一道比较明显的2-SAT(好吧,做到现在2-SAT的题目都挺明显的QAQ),答案不大,直接二分答案来做,要注意的建图过程。

  核心是找必须条件,如果 distance(i,j) < 2 * r,那么说明 i,j 点间的边不能连(一连就会有重叠面积),所以必须条件是:如果到 i 那么必须连 j^1,如果到 j 那么必须连 i^1。

  1 /*************************************************************************
  2     > File Name: 3622.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com 
  5     > Created Time: Thu 16 Oct 2014 09:20:58 PM CST
  6 ************************************************************************/
  7 
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <cstdlib>
 11 #include <cmath>
 12 #include <vector>
 13 #include <map>
 14 #include <set>
 15 #include <stack>
 16 #include <queue>
 17 #include <iostream>
 18 #include <algorithm>
 19 using namespace std;
 20 #define lp (p << 1)
 21 #define rp (p << 1|1)
 22 #define getmid(l,r) (l + (r - l) / 2)
 23 #define MP(a,b) make_pair(a,b)
 24 typedef long long ll;
 25 const int INF = 1 << 30;
 26 const double eps = 1e-6;
 27 
 28 int N,cnt;
 29 double x[205],y[205];
 30 double g[205][205];
 31 int low[205],dfn[205],sc[205],scnt,tot;
 32 vector<double> G[205];
 33 stack<int> S;
 34 double dmax;
 35 
 36 double Dis(int a,int b){
 37     return sqrt((x[b] - x[a]) * (x[b] - x[a]) + 
 38             (y[b] - y[a]) * (y[b] - y[a]));
 39 }
 40 
 41 void Cal_dis(){
 42     int top = 2 * N;
 43     for(int i = 0; i < top; ++i)
 44     for(int j = 0; j < top; ++j){
 45         g[i][j] = g[j][i] = Dis(i,j);
 46         dmax = g[i][j] > dmax ? g[i][j] : dmax;
 47     }
 48 }
 49 
 50 void Dfs(int p){
 51     dfn[p] = low[p] = ++tot;
 52     S.push(p);
 53     int top = G[p].size();
 54     for(int i = 0; i < top; ++i){
 55         int v = G[p][i];
 56         if(!dfn[v]){
 57             Dfs(v);
 58             low[p] = min(low[p],low[v]);
 59         }
 60         else if(!sc[v]){
 61             low[p] = min(low[p],dfn[v]);
 62         }
 63     }
 64     if(low[p] == dfn[p]){
 65         ++scnt;
 66         while(1){
 67             int x = S.top();
 68             S.pop();
 69             sc[x] = scnt;
 70             if(x == p) break;
 71         }
 72     }
 73 }
 74 
 75 void Tarjan(){
 76     memset(low,0,sizeof(low));
 77     memset(dfn,0,sizeof(dfn));
 78     memset(sc,0,sizeof(sc));
 79     while(!S.empty()) S.pop();
 80     scnt = tot = 0;
 81     int top = 2 * N;
 82     for(int i = 0; i < top; ++i)
 83         if(!dfn[i]) Dfs(i);
 84 }
 85 
 86 bool Solve(double d){
 87     //Build graph
 88     int top = 2 * N;
 89     for(int i = 0; i < top; ++i)
 90         G[i].clear();
 91     for(int i = 0; i < top; ++i){
 92         int j;
 93         if(i % 2) j = i + 1;
 94         else j = i + 2;
 95         for(; j < top; ++j){
 96             if(g[i][j] < 2 * d){
 97                 G[i].push_back(j ^ 1);
 98                 G[j].push_back(i ^ 1);
 99             }
100         }
101     }
102     //Judge
103     Tarjan();
104     for(int i = 0; i < N; ++i)
105         if(sc[i * 2] == sc[i * 2 + 1]) return false;
106     return true;
107 }
108 
109 int main(){
110     int x1,y1,x2,y2;
111     while(scanf("%d",&N) != EOF){
112         for(int i = 0; i < N; ++i){
113             scanf("%lf%lf%lf%lf",&x[i * 2],&y[i * 2],
114                     &x[i * 2 + 1],&y[i * 2 + 1]);
115         }
116         dmax = 0.0;
117         Cal_dis();
118         int top = 2 * N;
119         double ans,mid,L = 0,R = dmax;
120         while(fabs(R - L) >= eps){
121             mid = L + (R - L) / 2.0;
122             if(Solve(mid))
123                 L = mid;
124             else
125                 R = mid;
126         }
127         printf("%.2f\n",L);
128     }
129     return 0;
130 }            

 

posted @ 2014-10-16 23:08  Naturain  阅读(179)  评论(0)    收藏  举报