这题比较容易看出来是2-sat.
2-sat箴言:如果a与b矛盾,则添加单向边(a,b').
由题意可以看出:最好的情况是每个圆的半径都相等。
所以就可以二分枚举半径了:
对于每一个半径,用2-sat判断是否有解。
矛盾条件:圆心距小于周长的2倍。。
之后就可以直接用模板来解了:
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。。^_^ 。~~。