标签:
2 1 1 1 -1 -1 -1 -1 1 2 1 1 -1 -1 1 -1 -1 1
1.41 1.00
给n对炸弹可以放置的坐标位置,每对只能选一个,每个炸弹爆炸的范围半径都一样,
控制爆炸的半径使得所有的爆炸范围都不相交,求解这个最大半径.
直接二分答案,跑一波2-SAT就好。
//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 1e5+7;
const double eps = 1e-5;
int x[MAXN],y[MAXN];
struct node
{
int v,next;
} edge[MAXN];
int head[MAXN],index;
void add_edge(int u,int v)
{
edge[index].v=v;
edge[index].next=head[u];
head[u]=index++;
}
int DFN[MAXN],low[MAXN],stack_[MAXN],in_stack[MAXN],belong[MAXN];
int cir,top,temp;
void Tarjan(int u)
{
int p;
DFN[u]=low[u]=++temp;
in_stack[u]=1;
stack_[top++]=u;
for(int i=head[u]; i+1; i=edge[i].next)
{
int v=edge[i].v;
if(!DFN[v])
{
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(in_stack[v])
low[u]=min(low[u],DFN[v]);
}
if(low[u]==DFN[u])
{
++cir;
do
{
p=stack_[--top];
in_stack[p]=0;
belong[p]=cir;
}
while(p!=u);
}
}
double dist(int i,int j)
{
return sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
int main()
{
int n,m;
while(scanf("%d",&n)!=EOF)
{
for(int i=0; i<n<<1; ++i)
scanf("%d%d",&x[i],&y[i]);
double ans;
double l=0.0,r=40000.0,mid;
while(r-l>=eps)
{
mid=(l+r)/2.0;
temp=cir=top=index=0;
memset(DFN,0,sizeof(DFN));
memset(head,-1,sizeof(head));
memset(in_stack,0,sizeof(in_stack));
memset(belong,0,sizeof(belong));
for(int i=0; i<n<<1; ++i)
for(int j=i+1; j<n<<1; ++j)
{
if(j-i==1&&i&1==0)continue;
if(dist(i,j)<mid*2.0)
{
add_edge(j^1,i);
add_edge(i^1,j);
}
}
for(int i=0; i<n<<1; ++i)
if(!DFN[i])Tarjan(i);
int flag=0;
for(int i=0; i<n; ++i)
if(belong[i<<1]==belong[(i<<1)^1])
{
flag=1;
break;
}
if(!flag){ans=mid;l=mid;}
else r=mid;
}
printf("%.2lf\n",ans);
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/qq978874169/article/details/51366649