2 1 1 1 -1 -1 -1 -1 1 2 1 1 -1 -1 1 -1 -1 1
1.41 1.00
思路:二分最小距离-2-sat 判断可行性,强连通缩点,判断a,a^1不矛盾就行了。
(a,b)矛盾则(a,b^1),(b,a^1)加边,不可盲目加双向边。
这题坑了我近7个小时,两个问题。
1:加了双向边
2:tarjan()有错 instack忘给退了。
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; const int mm=200+9; const double eps=1e-6; class node { public: double x,y; } f[mm]; int n; double dis[mm][mm]; int head[mm],stack[mm],top,cnt,edge,dex,dfn[mm],low[mm],e_to[mm]; int ver[mm*mm],next[mm*mm]; bool instack[mm]; void data() { memset(head,-1,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(instack,0,sizeof(instack)); dex=top=cnt=edge=0; } void add(int u,int v) { if(u==v)return; ver[edge]=v; next[edge]=head[u]; head[u]=edge++; // ver[edge]=u; //next[edge]=head[v]; //head[v]=edge++; } double get_dis(node a,node b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } void tarjan(int u) { dfn[u]=low[u]=++dex; stack[top++]=u; instack[u]=1; int v; for(int i=head[u]; ~i; i=next[i]) { v=ver[i]; if(!dfn[v]) { tarjan(v); low[u]=low[u]<low[v]?low[u]:low[v]; } else if(instack[v]) { low[u]=low[u]<dfn[v]?low[u]:dfn[v]; } } if(dfn[u]==low[u]) { ++cnt; do { v=stack[--top]; instack[v]=0; e_to[v]=cnt; } while(v^u); } } bool two_sat(double x) { for(int i=0; i<n; ++i) for(int j=i+1; j<n; ++j) if(j^i&&dis[i][j]<x) { add(i,j^1),add(j,i^1); // add(j^1,i);add(i^1,j); // printf("dis=%lf %d -> %d\n",dis[i][j],i,j); //printf("%d %d\n %d %d\n",i,j^1,j,i^1); } for(int i=0; i<n; ++i) if(!dfn[i]) tarjan(i); // for(int i=0;i<n;++i) // cout<<i<<" "<<e_to[i]<<endl; for(int i=0; i<n; ++i) if(e_to[i]==e_to[i^1])return 0; return 1; } int main() { ///freopen("data.in","r",stdin); while(~scanf("%d",&n)) { for(int i=0; i<n; ++i) scanf("%lf%lf%lf%lf",&f[i+i].x,&f[i+i].y,&f[i+i+1].x,&f[i+i+1].y); n+=n; for(int i=0; i<n; ++i) for(int j=i+1; j<n; ++j) dis[i][j]=get_dis(f[i],f[j]); double l=0.0,r=1e9,mid; while(r-l>eps) { data(); mid=(l+r)/2.0; // mid=3.80; // puts("......................................................"); // printf("%lf----\n",mid); if(two_sat(mid*2.0)) {l=mid;} else {r=mid;} } printf("%.2lf\n",(l+r)/2.0); } }