题意:有n对点,每对点只能选择一个点画圈,要求圈不相交,,问圈的最大半径。。
思路。浮点数计算很花时间,用半径的平方,进行计算。一般的2-sat
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> using namespace std; const int INF = 0x3f3f3f3f; const int N = 209; struct cvecter{ int x,y; cvecter(int a,int b){x=a,y=b;} cvecter(){} }; int operator*(cvecter &a,cvecter &b){ return a.x*b.x+a.y*b.y; } int length(int t){return t<0?-t:t;} int length(cvecter t){return t*t;} struct cpoint{ int x,y; cpoint(int &a,int &b){x=a,y=b;} cpoint(){} }; cvecter operator-(cpoint &a,cpoint &b){ return cvecter(a.x-b.x,a.y-b.y); } struct cline{ cpoint a,b; } re[109]; int n; struct LT{ int to,nex; }L[N*N]; int F[N],cnt; void add(int f,int t) { L[cnt].nex = F[f]; L[cnt].to = t; F[f] = cnt++; } int dfn[N],low[N],col[N],post[N],color,ind; stack<int> S; void tdfs(int k) { low[k] = dfn[k] = ++ind; post[k] = 1;S.push(k); for(int i=F[k];i;i=L[i].nex) { int to = L[i].to; if(!dfn[to]) { tdfs(to); low[k] = min(low[k],low[to]); }else if(post[to]&&dfn[to]<low[k]) low[k] = dfn[to]; } if(low[k]==dfn[k]) { int i;color++; for(i=S.top(),S.pop();i!=k;i=S.top(),S.pop()) col[i]=color,post[i]=0; col[k]=color,post[k]=0; } } bool tarjan() { memset(dfn,0,sizeof(dfn)); color=0;ind=0; for(int i=0;i<(n<<1);i++) if(!dfn[i]) tdfs(i); for(int i=0;i<n;i++) if(col[i]==col[i+n]) return false; return true; } void solve() { int l=0,r=INF,mid; int ans; while(l<=r) { mid = (l+r)>>1; memset(F,0,sizeof(F));cnt=1; for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { if(length(re[i].a-re[j].a)<mid) add(i,j+n),add(j,i+n); if(length(re[i].a-re[j].b)<mid) add(i,j),add(j+n,i+n); if(length(re[i].b-re[j].a)<mid) add(i+n,j+n),add(j,i); if(length(re[i].b-re[j].b)<mid) add(i+n,j),add(j+n,i); } } if(tarjan()) ans = mid,l=mid+1; else r=mid-1; } printf("%.2lf\n",sqrt(ans*1.0)/2); } int main() { freopen("in.txt","r",stdin); while(~scanf("%d",&n)) { for(int i=0;i<n;i++) scanf("%d%d%d%d",&re[i].a.x,&re[i].a.y,&re[i].b.x,&re[i].b.y); solve(); } return 0; }