这题比较容易看出来是2-sat.
2-sat箴言:如果a与b矛盾,则添加单向边(a,b').
由题意可以看出:最好的情况是每个圆的半径都相等。
所以就可以二分枚举半径了:
对于每一个半径,用2-sat判断是否有解。
矛盾条件:圆心距小于周长的2倍。。
之后就可以直接用模板来解了:
View Code
1 # include<stdio.h>
2 # include<math.h>
3 # define N 205
4 # define M 40005
5 struct node{
6 int x,y;
7 }s[N];
8 struct node1{
9 int from,to,next;
10 }edge1[M],edge2[M];
11 int visit1[N],visit2[N],head1[N],head2[N],Belong[N],T[N];
12 int tol1,tol2,Bcnt,Tcnt;
13 void add(int a,int b)
14 {
15 edge1[tol1].from=a;edge1[tol1].to=b;edge1[tol1].next=head1[a];head1[a]=tol1++;
16 edge2[tol2].from=b;edge2[tol2].to=a;edge2[tol2].next=head2[b];head2[b]=tol2++;
17 }
18 void dfs1(int x)
19 {
20 int j;
21 visit1[x]=1;
22 for(j=head1[x];j!=-1;j=edge1[j].next)
23 if(visit1[edge1[j].to]==0) dfs1(edge1[j].to);
24 T[Tcnt++]=x;
25 }
26 void dfs2(int x)
27 {
28 int j;
29 visit2[x]=1;
30 Belong[x]=Bcnt;
31 for(j=head2[x];j!=-1;j=edge2[j].next)
32 if(visit2[edge2[j].to]==0) dfs2(edge2[j].to);
33 }
34 double dist(int x1,int y1,int x2,int y2)
35 {
36 return sqrt((x1 -x2)*(x1-x2) + (y1-y2)*(y1-y2));
37 }
38 int main()
39 {
40 int i,j,n,ans;
41 double left,right,mid,Max,ans1;
42 while(scanf("%d",&n)!=EOF)
43 {
44 for(i=1;i<=n;i++)
45 scanf("%d%d%d%d",&s[2*i-1].x,&s[2*i-1].y,&s[2*i].x,&s[2*i].y);
46 right=20000*sqrt(2);
47 left=0;
48 Max=0;
49 while(right - left>=1e-4)
50 {
51 mid=(right+left)/2;
52 for(i=0;i<=2*n;i++)
53 {
54 head1[i]=-1;
55 head2[i]=-1;
56 visit1[i]=0;
57 visit2[i]=0;
58 }
59 tol1=tol2=Bcnt=Tcnt=0;
60 for(i=1;i<2*n-1;i++)
61 {
62 if(i%2==1) ans=i+2;
63 else ans=i+1;;
64 for(j=ans;j<=2*n;j++)
65 {
66 ans1=dist(s[i].x,s[i].y,s[j].x,s[j].y);
67 if(ans1 < 2*mid )
68 {
69 if(i%2==0 && j%2==0)
70 {
71 add(i,j-1);
72 add(j,i-1);
73 }
74 else if(i%2==0 && j%2==1)
75 {
76 add(i,j+1);
77 add(j,i-1);
78 }
79 else if(i%2==1 && j%2==0)
80 {
81 add(i,j-1);
82 add(j,i+1);
83 }
84 else
85 {
86 add(i,j+1);
87 add(j,i+1);
88 }
89 } //if
90 }//for
91 }//for
92 for(i=1;i<=2*n;i++)
93 if(visit1[i]==0) dfs1(i);
94 for(i=Tcnt-1;i>=0;i--)
95 {
96 if(visit2[T[i]]==0)
97 {
98 dfs2(T[i]);
99 Bcnt++;
100 }
101 }
102 for(i=1;i<=2*n-1;i+=2)
103 {
104 if(Belong[i] == Belong[i+1]) break;
105 }
106 if(i<=2*n-1) right=mid -(1e-4);
107 else {Max=mid;left=mid+(1e-4);}
108 }
109 printf("%.2lf\n",Max);
110 }
111 return 0;
112 }
去年成都现场赛有道题:3715 Go Deeper 也是一道2-sat题,不过不太容易看出来,至于满足矛盾条件建立边时,我到现在还不是很理解,
不知道两位学长当时是怎么看出来的。。Orz个。。 等到省赛之后,再来继续研究吧。。
后天就要去参加省赛了,心理有点小激动。。 尽管去年还去了趟成都,但那时还有学长,我就是去打酱油的,没有太大的压力。这次可不一样,这次一定不能打酱油。。。
希望大后天 RP可以baobaobao。。^_^ 。~~。