标签:
时间限制:1000MS
内存限制:131072KB
接上回(本OJ的《P2107. Zrn神犇之还原数据》),Zrn神犇还原完数据,发现机房的网络连接全部中断了。他准备把机房的网络恢复起来。
机房里有若干台整齐排放的电脑和一个路由器。路由器可以提供无线网络连接(又称Wi-Fi),覆盖区域是一个以它为圆心的圆。并且,如果某个电脑联网了,它可以建立Wi-Fi热点,为其它电脑提供网络连接,类似地,覆盖区域也是一个同样大小的圆。但是,如果某个电脑无法通过Wi-Fi联网的话,它就必须通过网线连接,但是同样可以设置Wi-Fi热点。
Zrn神犇已经将路由器成功地连上了外网。现在问题来了,由于机房的机子众多,而且都没有编程软件,Zrn神犇只能把各个机器的坐标写成一个文件,不惜他的手机流量传给你。请你帮助他计算一下,至少要购买多少条网线吧。
第一行,四个整数n、x、y、r,分别表示有n台电脑、路由器在机房中的坐标和它的Wi-Fi覆盖半径。
以后的n行每行两个整数Xi、Yi,表示该电脑的坐标。
仅一行,表示最少要购买多少条网线。
10 1 1 1 1 2 1 3 1 4 1 5 2 6 2 7 3 10 3 8 2 10 2 8
2
对于所有数据满足n≤5000,x、y、r和Xi、Yi均在short int范围内。r≥0。
数据十分有梯度!而且有坑!
【题解】
话说数据真的有坑!
不仅卡精度,sqrt过不了,而且还要long long。
其实就是简单的并查集。
不过套了个平面模型。
这也算计算几何?并不懂。反正我只会勾股定理。
用平方来比较即可。
注意r*r是可以提前计算的,不必重复计算,可提升效率。
加了读入优化2.0还是0.7s呜呜呜~
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,r,pre[5010],x[5010],y[5010]; 4 char B[1<<15],*S=B,*T=B; 5 char getchar2() { 6 return S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?0:*S++; 7 } 8 int getf(int x) { 9 int r=x; 10 while(pre[r]!=r) 11 r=pre[r]; 12 int i=x,j; 13 while(i!=r) { 14 j=pre[i]; 15 pre[i]=r; 16 i=j; 17 } 18 return r; 19 } 20 int read() { 21 int x=0,f=1; 22 char ch=getchar2(); 23 while(ch<‘0‘||ch>‘9‘) {if(ch==‘-‘) f=-1; ch=getchar2();} 24 while(ch>=‘0‘&&ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar2();} 25 return x*f; 26 } 27 int main() { 28 n=read();x[0]=read();y[0]=read();r=read();r*=r; 29 for (int i=1;i<=n;++i) pre[i]=i; 30 for (int i=1;i<=n;++i) { 31 x[i]=read(),y[i]=read(); 32 for (int j=0;j<i;++j) 33 if((long long)(x[i]-x[j])*(long long)(x[i]-x[j])+(long long)(y[i]-y[j])*(long long)(y[i]-y[j])<=(long long)r) pre[getf(i)]=getf(j); 34 } 35 int ans=0; 36 for (int i=0;i<=n;++i) if(pre[i]==i) ans++; 37 printf("%d\n",ans-1); 38 return 0; 39 }
标签:
原文地址:http://www.cnblogs.com/TonyNeal/p/fzyzoj2108.html