地址:
点击打开链接
这个题目,如果不是同一个组(设当前点为i,测到的组为j),那么就判断是不是<dis(二分),如果小于,那么就连接i与j^1,这个时候,如果i与j与j^1都行不通,那么就无法实现每组选一个,也就是说当前的dis无法实现(在代码上表现就是构成了强连通分量,想一想i 与 j^1 ,连接了,同时j 与 i^1连接了,而走到j+1的时候,发现i又与j+1^1构边了,同时j+1也和i^1构边了,因此就形成了一个强连通分量,说明不可行),需要再进行二分。
代码:
#include<cstring> #include<cstdio> #include<cmath> #include<algorithm> const int MAXN=210; const int MAXM=41000; const double eps=1e-5; using namespace std; struct node{ int x,y; }p[MAXN]; struct Edge{ int to,next; }edge[MAXM<<1];int head[MAXN],tot; void init(){ tot=0; memset(head,0xff,sizeof(head)); } void addedge(int u,int v){ edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } int low[MAXN],dfn[MAXN],sccno[MAXN],scc_cnt,dfs_clock; int Stack[MAXN],top; bool instack[MAXN]; void dfs(int u){ int v; Stack[top++]=u; instack[u]=1; low[u]=dfn[u]=++dfs_clock; for(int i=head[u];i!=-1;i=edge[i].next){ v=edge[i].to; if(!dfn[v]){ dfs(v); low[u]=min(low[u],low[v]); } else if(instack[v]&&low[u]>dfn[v]){ low[u]=dfn[v]; } } if(low[u]==dfn[u]){ ++scc_cnt; for(;;){ v=Stack[--top]; instack[v]=0; sccno[v]=scc_cnt; if(v==u) break; } } } bool solveable(int n){ memset(dfn,0,sizeof(dfn)); memset(instack,false,sizeof(instack)); dfs_clock=scc_cnt=top=0; for(int i=0;i<n;++i){ if(!dfn[i]) dfs(i); } for(int i=0;i<n;i+=2){ if(sccno[i]==sccno[i^1]) return false; } return true; } double dist(node a,node b){ return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } void Build_graph(int n,double m){ init(); for(int i=0;i<2*n;++i){ for(int j=0;j<2*n;++j){ if(i/2!=j/2&&dist(p[i],p[j])<m){ addedge(i,j^1); addedge(j,i^1); } } } } int main(){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif // ONLINE_JUDGE int n; while(scanf("%d",&n)!=EOF){ for(int i=0;i<n;++i){ scanf("%d%d%d%d",&p[2*i].x,&p[2*i].y,&p[2*i+1].x,&p[2*i+1].y); } double l=0.0,r=40000.0; while(r-l>=eps){ double m=(l+r)/2.0; Build_graph(n,2*m); if(solveable(2*n)) l=m; else r=m; } printf("%.2lf\n",l); } return 0; }