zoj 3717 二分+2sat tarjan求强连通

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <map>

using namespace std;
#define ll long long 
#define inf 0x3f3f3f3f
#define mod 1000000007
#define eps 1e-8
#define N 410
#define M 1001000
int n;
struct P
{
	int x,y,z;
	void input()
	{
		scanf("%d%d%d",&x,&y,&z);
	}
}p[N];
int h[N],vv[M],nxt[M],e;
int dfn[N],low[N],sta[N],be[N],top,cnt,idx,insta[N];
double d[N][N];

void add(int u,int v)
{
	vv[e] = v, nxt[e] = h[u], h[u] = e++;
}
int dblcmp(double x)
{
	return (x>eps)-(x<-eps);
}
double dis(int i,int j)
{
	return sqrt(.0+(p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y)+(p[i].z-p[j].z)*(p[i].z-p[j].z));
}
void tarjan(int u)
{
	dfn[u] = low[u] = ++idx;
	insta[u] = 1;
	sta[++top] = u;
	for(int i=h[u];i+1;i=nxt[i])
	{
		int v = vv[i];
		if(!dfn[v])
		{
			tarjan(v);
			low[u] = min(low[u],low[v]);
		}
		else if(insta[v])
		{
			low[u] = min(low[u],dfn[v]);
		}
	}
	if(low[u]==dfn[u])
	{
		++cnt;
		while(top>=1)
		{
			be[sta[top]] = cnt;
			insta[sta[top]] = 0;
			top--;
			if(sta[top+1]==u) break;
		}
	}
}
bool check(double r)
{
	memset(h,-1,sizeof(h));
	e = 0;
	for(int i=0;i<n;i++)
	{
		for(int j=i+1;j<n;j++)
		{
			if(dblcmp(d[i][j]-2*r)<0)
				add(i,j+n),add(j,i+n);
			if(dblcmp(d[i][j+n]-2*r)<0)
				add(i,j),add(j+n,i+n);
			if(dblcmp(d[i+n][j]-2*r)<0)
				add(i+n,j+n),add(j,i);
			if(dblcmp(d[i+n][j+n]-2*r)<0)
				add(i+n,j),add(j+n,i);

		}
	}
	top = cnt = 0;
	memset(dfn,0,sizeof(dfn));
	memset(be,0,sizeof(be));
	memset(insta,0,sizeof(insta));
	for(int i=0;i<2*n;i++)
		if(!dfn[i])
			tarjan(i);
	for(int i=0;i<n;i++)
		if(be[i]==be[i+n]) return false;
	return true;
}
double solve()
{
	double l = 0, r = 1e10,mid;
	while(l+eps<r)
	{
		mid = (l+r)/2;
		if(check(mid)) l = mid;
		else r = mid;
	}
	return l;
}
int main()
{

	while(scanf("%d",&n)!=EOF)
	{
		for(int i=0;i<n;i++)
			p[i].input(),p[i+n].input();
		for(int i=0;i<2*n;i++)
			for(int j=i+1;j<2*n;j++)
				d[i][j] = d[j][i] = dis(i,j);
		double ans = solve();
		int tmp = ans*1000;
		ans = tmp/1000.0;
		printf("%.3lf\n",ans);
	}
}

下面是别人的写法:

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;

const int N=410;

struct Point
{
    int x,y,z;
}point[N];

struct Dis
{
    int dis,x,y;
}d[N*N];

int n,dlen;

vector<int> G[N<<1];
bool mark[N<<1];
int s[N<<1],cnt;

bool DFS(int x)
{
    if(mark[x^1]) return false;
    if(mark[x]) return true;
    mark[x]=true;
    s[cnt++]=x;
    for(int i=0;i<G[x].size();++i)
        if(!DFS(G[x][i])) return false;
    return true;
}

bool solve()
{
    for(int i=2;i<=n*2;i+=2) {
        if(!mark[i]&&!mark[i+1]) {
            cnt=0;
            if(!DFS(i)) {
                while(cnt) mark[s[--cnt]]=false;
                if(!DFS(i+1)) return false;
            }
        }
    }
    return true;
}

int dist(int i,int j)
{
    return (point[i].x-point[j].x)*(point[i].x-point[j].x)+
            (point[i].y-point[j].y)*(point[i].y-point[j].y)+
            (point[i].z-point[j].z)*(point[i].z-point[j].z);
}

bool cmp(Dis A,Dis B)
{
    return A.dis<B.dis;
}

void init()
{
    for(int i=0;i<=n*2;++i)
        G[i].clear();
    memset(mark,false,sizeof mark);
}

bool judge(int mid)
{
    int x,y;
    init();
    int t=n/2;
    for(int i=1;i<=t;++i) {
        x=i*2;
        y=(t+i)*2;
        G[x].push_back(y^1);
        G[y].push_back(x^1);
    }
    for(int i=0;i<mid;++i) {
        x=d[i].x;
        y=d[i].y;
        x*=2;
        y*=2;
        G[x^1].push_back(y);
        G[y^1].push_back(x);
    }
    return solve();
}

int main()
{
    int x,y;
    bool flag;
    int ans,np;
    int L,R,mid;
    double hehe;
    while(scanf("%d",&n)==1) {
        init();
        dlen=0;
        for(int i=1;i<=n;++i) {
            scanf("%d%d%d%d%d%d",&point[i].x,&point[i].y,&point[i].z,
                  &point[i+n].x,&point[i+n].y,&point[i+n].z);
        }
        n*=2;
        for(int i=1;i<=n;++i) {
            for(int j=i+1;j<=n;++j) {
                d[dlen].x=i;
                d[dlen].y=j;
                d[dlen++].dis=dist(i,j);
            }
        }
        sort(d,d+dlen,cmp);
        ans=d[0].dis;
        np=0;
        L=0,R=dlen-1;
        while(L<=R) {
            mid=L+(R-L)/2;
            if(judge(mid)) {
                L=mid+1;
                ans=d[mid].dis;
            }
            else R=mid-1;
        }
        hehe=sqrt(double(ans))/2;
        printf("%.3lf\n",(int)(hehe*1000)/1000.0);
    }
}












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值