HDU 3622 2-SAT
第一道2-SAT
题意:有N对点,给出N对点的坐标,要求找出一个最大的半径R,使得可以从每对点中选择一个点,并且这N个点以自己为圆心,半径为R的圆两两不相交。
对于2*N个点,如果两个点之间“矛盾”,即两个圆相交,就连一条边。意思是:我选了这个点之后,无法选另外一组的某个点,就只能选某个点的兄弟点。对这个图求强连通分量,然后看是否有某对点属于同一个强连通分量。如果N对点每一对都属于不同的强连通分量,满足。否则不满足。然后二分答案即可。
#include <stdio.h> #include <algorithm> #include <cstring> #include <iostream> #include <math.h> #include <stdlib.h> #include <map> #include <vector> using namespace std; const double eps=1e-4; struct point { int x; int y; }a[210]; double dis(point a,point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } const int MAXN=210; struct node { int v; int nxt; }; node edge[MAXN*MAXN];//边数 int head[MAXN]; int n,m; int Stop,Bcnt,Dindex;//栈头,强通块数,时间戳 int DFN[MAXN],LOW[MAXN];//首时间戳,最近回溯点(根) int Stap[MAXN];//答案栈 int instack[MAXN];//是否在栈中 int Belong[MAXN];//这个点属于第几个强连通块(点) int cnt=0; void add_edge(int u,int v) { edge[cnt].v=v; edge[cnt].nxt=head[u]; head[u]=cnt; cnt++; } void tarjan(int i) { int j; DFN[i]=LOW[i]=++Dindex; instack[i]=1; Stap[++Stop]=i; for (int e=head[i]; e!=-1; e=edge[e].nxt) { j=edge[e].v; if (!DFN[j])//儿子没遍历 { tarjan(j);//遍历 if (LOW[j]<LOW[i])//如果儿子已经形成环 LOW[i]=LOW[j];//父亲也要在回溯的时候进入环 } else if (instack[j]&&DFN[j]<LOW[i])//邻接的在栈里,所以是大大 LOW[i]=DFN[j];//把这个点归到大大那 } if (DFN[i]==LOW[i])//这个点的根是自己 { Bcnt++;//多了一个强连通分量 do { j=Stap[Stop--];//退栈 instack[j]=0;//标记 Belong[j]=Bcnt;//标记 } while (j!=i); } } int solve() { int i; Stop=Bcnt=Dindex=0;//栈头,强通块数,时间戳 memset(DFN,0,sizeof(DFN)); for (int i=0; i<2*n; i++) { // printf ("dfn[i]\%d\n",DFN[i]); if (!DFN[i]) tarjan(i); } for (int i=0;i<2*n;i+=2)//不在一个联通块里 { if (Belong[i]==Belong[i+1]) return 0; } return 1; } int main() { while (scanf ("%d",&n)!=EOF) { for (int i=0;i<2*n;i+=2) { scanf ("%d%d",&a[i].x,&a[i].y); scanf ("%d%d",&a[i+1].x,&a[i+1].y); } double r=40001,l=0; while (r-l>eps) { double mid=(l+r)/2.0; memset(head,-1,sizeof(head)); cnt=0; for (int i=0;i<2*n;i++) { for (int j=i+1;j<2*n;j++) { if ((i!=(j^1))&&(dis(a[i],a[j])<2*mid)) { add_edge(i,j^1); add_edge(j,i^1); } } } if (solve()) { l=mid; } else r=mid; } printf ("%.2f\n",l); } return 0; }
浙公网安备 33010602011771号