zoj 3717 Balloon 2-sat

题目:给出空间中的n对点,要求从每对点中选出一个,使得最近的点的距离最远。

分析:

  二分的思想很明显,二分答案之后,建图:如果两点之间的距离小于二分值时,连接相应的边,通过2-sat判断一下即可。

  注意到题目的要求是向下取整,于是我们可以先*10000,最后直接取模即可。

 

 

#include <set>

#include <map>

#include <list>

#include <cmath>

#include <queue>

#include <stack>

#include <string>

#include <vector>

#include <cstdio>

#include <cstring>

#include <iostream>

#include <algorithm>



using namespace std;



typedef long long ll;

typedef unsigned long long ull;



#define debug puts("here")

#define rep(i,n) for(int i=0;i<n;i++)

#define rep1(i,n) for(int i=1;i<=n;i++)

#define REP(i,a,b) for(int i=a;i<=b;i++)

#define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)

#define pb push_back

#define RD(n) scanf("%d",&n)

#define RD2(x,y) scanf("%d%d",&x,&y)

#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)

#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)

#define All(vec) vec.begin(),vec.end()

#define MP make_pair

#define PII pair<int,int>

#define PQ priority_queue

#define cmax(x,y) x = max(x,y)

#define cmin(x,y) x = min(x,y)

#define Clear(x) memset(x,0,sizeof(x))



/******** program ********************/

const int MAXN = 405;

const int MAXM = 1000005;



int low[MAXN],sta[MAXN],dfn[MAXN],fa[MAXN],dep,bcnt,top;

bool use[MAXN];

int po[MAXN],tol,n,m;



struct Edge {

    int y,next;

} edge[MAXM];



struct Point {

    int a[3];

    void rd() {

        RD3(a[0],a[1],a[2]);

        a[0] *= 10000;

        a[1] *= 10000;

        a[2] *= 10000;

    }

} p[MAXN][2];



void add(int x,int y) {

    edge[++tol].y = y;

    edge[tol].next = po[x];

    po[x] = tol;

}



void dfs(int x) {

    sta[++top] = x;

    use[x] = true;

    low[x] = dfn[x] = ++ dep;

    int y;

    for(int i=po[x]; i; i=edge[i].next) {

        y = edge[i].y;

        if(!dfn[y]) {

            dfs(y);

            low[x] = min(low[x],low[y]);

        } else if(use[y])

            low[x] = min(low[x],dfn[y]);

    }

    if(low[x]==dfn[x]) {

        ++ bcnt;

        do {

            y = sta[top--];

            use[y] = false;

            fa[y] = bcnt;

        } while(x!=y);

    }

}



bool sat() {

    memset(dfn,0,sizeof(dfn));

    memset(use,false,sizeof(use));

    dep = top = bcnt = 0;

    rep1(i,2*n)

    if(!dfn[i])

        dfs(i);

    rep1(i,n)

    if(fa[i]==fa[i+n])

        return false;

    return true;

}



ll sqr(ll x) {

    return x*x;

}



ll dist(Point a,Point b) {

    return sqr(a.a[0]-b.a[0])+sqr(a.a[1]-b.a[1])+sqr(a.a[2]-b.a[2]);

}



bool solve(ll mid) {

    memset(po,0,sizeof(po));

    tol = 0;

    rep1(i,n) {

        rep1(j,n) {

            if(i==j)continue;

            ll d = dist(p[i][0],p[j][0]);

            if(d<mid) {

                add(i,j+n);

                add(j,i+n);

            }



            d = dist(p[i][0],p[j][1]);

            if(d<mid) {

                add(i,j);

                add(j+n,i+n);

            }



            d = dist(p[i][1],p[j][0]);

            if(d<mid) {

                add(i+n,j+n);

                add(j,i);

            }



            d = dist(p[i][1],p[j][1]);

            if(d<mid) {

                add(i+n,j);

                add(j+n,i);

            }

        }

    }

    return sat();

}



int main() {

#ifndef ONLINE_JUDGE

    freopen("sum.in", "r", stdin);

    // freopen("cf.out", "w", stdout);

#endif



    while(~RD(n)) {

        rep1(i,n) {

            p[i][0].rd();

            p[i][1].rd();

        }

        ll ans = -1 , l = 0 , r = 2000000000LL;

        while(l<=r) {

            ll mid = (l+r)/2;

            if(solve(mid*mid)) {

                l = mid+1;

                ans = mid;

            } else r = mid-1;

        }

        printf("%lld.%03lld\n",ans/20000,(ans/2%10000)/10 );

    }



    return 0;

}

 

  

 

你可能感兴趣的:(ZOJ)