题面
现有一块大奶酪,它的高度为 h,它的长度和宽度我们可以认为是无限大的,奶酪中间有许多 半径相同 的球形空洞。我们可以在这块奶酪中建立空间坐标系,在坐标系中,奶酪的下表面为z = 0,奶酪的上表面为z = h。
现在,奶酪的下表面有一只小老鼠 Jerry,它知道奶酪中所有空洞的球心所在的坐标。两相切或是相交,则 Jerry 可以从其中一个空洞跑到另一个,特别地,如果一个空洞与下表面相切或是相交,Jerry 则可以从奶酪下表面跑进空洞;如果一个空洞与上表面相切或是相交,Jerry 则可以从空洞跑到奶酪上表面。
位于奶酪下表面的 Jerry 想知道,在 不破坏奶酪 的情况下,能否利用已有的空洞跑到奶酪的上表面去?
分析
去年不会,真的是因为去年那个时候还没学并查集,然后我是没看出来怎么跑spfa的,但是并查集很显然。
怕爆int 给h和r也开了个double 刚刚做WA了一发,因为我把初始化fa写在了输入n之前,我怎么这么菜啊。
代码
- #include<bits/stdc++.h>
- using namespace std;
- #define N 1010
- struct email
- {
- double x,y,z;
- }p[N];
- int t,n;
- double h,r;
- int fa[N];
- inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
- inline double dis(email p1,email p2)
- {return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)+(p1.z-p2.z)*(p1.z-p2.z));}
- inline void combine(int x,int y)
- {
- int fax=find(x),fay=find(y);
- if(fax!=fay)fa[fax]=fay;
- }
- int main()
- {
- scanf("%d",&t);
- while(t--)
- {
- scanf("%d%lf%lf",&n,&h,&r);
- for(int i=1;i<=n+2;i++)fa[i]=i;
- for(int i=1;i<=n;i++)
- {
- scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
- if((p[i].z<=r&&p[i].z>=0)||(-p[i].z<=r&&p[i].z<=0))combine(n+1,i);
- if((p[i].z<=h+r&&p[i].z>=h)||(-p[i].z<=r-h&&p[i].z<=h))combine(n+2,i);
- }
- for(int i=1;i<=n;i++)
- for(int j=i+1;j<=n;j++)
- if(dis(p[i],p[j])<=2*r)combine(i,j);
- if(find(n+1)==find(n+2))printf("Yes ");
- else printf("No ");
- }
- }