NOIP 2017 提高组 K: 奶酪 (SPFA || 并查集)
K: 奶酪
时间限制: 1 Sec 内存限制: 128 MB提交: 115 解决: 30
[提交][状态][讨论版]
题目描述
现有一块大奶酪,它的高度为 h ,它的长度和宽度我们可以认为是无限大的,奶酪中间有许多半径相同的球形空洞。我们可以在这块奶酪中建立空间坐标系,在坐标系中,奶酪的下表面为 z = 0 ,奶酪的上表面为 z = h 。
现在,奶酪的下表面有一只小老鼠 Jerry ,它知道奶酪中所有空洞的球心所在的坐标。如果两个空洞相切或是相交,则 Jerry 可以从其中一个空洞跑到另一个空洞,特别地,如果一个空洞与下表面相切或是相交, Jerry 则可以从奶酪下表面跑进空洞;如果一个空洞与上表面相切或是相交, Jerry 则可以从空洞跑到奶酪上表面。
位于奶酪下表面的 Jerry 想知道,在不破坏奶酪的情况下,能否利用已有的空洞跑到奶酪的上表面去 ?
P1(x1,y1,z1)、P2(x_2,y_2,z_2)P2(x2,y2,z2)的距离公式如下:
![](http://exam.upc.edu.cn/upload/image/20171121/20171121173140_10044.jpg)
现在,奶酪的下表面有一只小老鼠 Jerry ,它知道奶酪中所有空洞的球心所在的坐标。如果两个空洞相切或是相交,则 Jerry 可以从其中一个空洞跑到另一个空洞,特别地,如果一个空洞与下表面相切或是相交, Jerry 则可以从奶酪下表面跑进空洞;如果一个空洞与上表面相切或是相交, Jerry 则可以从空洞跑到奶酪上表面。
位于奶酪下表面的 Jerry 想知道,在不破坏奶酪的情况下,能否利用已有的空洞跑到奶酪的上表面去 ?
P1(x1,y1,z1)、P2(x_2,y_2,z_2)P2(x2,y2,z2)的距离公式如下:
![](http://exam.upc.edu.cn/upload/image/20171121/20171121173140_10044.jpg)
输入
包含多组数据。
第一行,包含一个正整数 T,代表该输入文件中所含的数据组数。
接下来是 T 组数据,每组数据的格式如下:
第一行包含三个正整数 n,h 和 r,两个数之间以一个空格分开,分别代表奶酪中空洞的数量,奶酪的高度和空洞的半径。
接下来的 n 行,每行包含三个整数 x、y、z,两个数之间以一个空格分开,表示空洞球心坐标为(
第一行,包含一个正整数 T,代表该输入文件中所含的数据组数。
接下来是 T 组数据,每组数据的格式如下:
第一行包含三个正整数 n,h 和 r,两个数之间以一个空格分开,分别代表奶酪中空洞的数量,奶酪的高度和空洞的半径。
接下来的 n 行,每行包含三个整数 x、y、z,两个数之间以一个空格分开,表示空洞球心坐标为(
输出
输出包含T行,分别对应T组数据的答案,如果在第i组数据中,Jerry能从下表面跑到上表面,则输出Yes,如果不能,则输出No(均不包含引号)。
样例输入
3
2 4 1
0 0 1
0 0 3
2 5 1
0 0 1
0 0 4
2 5 2
0 0 2
2 0 4
样例输出
Yes
No
Yes
提示
【题意】
题意很明确 能否从下面到上面
【思路】
转换方向, 就是一个图, 类似于 网络流 有一个 源点 和汇点, 唯一不同的就是 图里面 没有权值, 这样 其实 也可以用并查集, 源点 汇点 看看 最后是否在一个队里, 如果在 那么 就yes 否则 就 no spfa 好理解, 从源点看看 汇点 可不可达
【代码实现】
SPFA 头文件 什么的 可以忽略~
//#include <bits/stdc++.h> #include <iostream> #include <stdio.h> #include <algorithm> #include <cmath> #include <math.h> #include <cstring> #include <string> #include <queue> #include <deque> #include <stack> #include <stdlib.h> #include <list> #include <map> #include <set> #include <bitset> #include <vector> #define mem(a,b) memset(a,b,sizeof(a)) #define findx(x) lower_bound(b+1,b+1+bn,x)-b #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w",stdout) #define S1(n) scanf("%d",&n) #define SL1(n) scanf("%I64d",&n) #define S2(n,m) scanf("%d%d",&n,&m) #define SL2(n,m) scanf("%I64d%I64d",&n,&m) #define Pr(n) printf("%d\n",n) #define lson rt << 1, l, mid #define rson rt << 1|1, mid + 1, r #define FI(n) IO::read(n) #define Be IO::begin() using namespace std; typedef long long ll; const double PI=acos(-1); const int INF=0x3f3f3f3f; const double esp=1e-6; const int maxn=1e5+5; const int MAXN=50005; const int MOD=1e9+7; const int mod=1e9+7; int dir[5][2]={0,1,0,-1,1,0,-1,0}; namespace IO { const int MT = 5e7; char buf[MT]; int c,sz; void begin(){ c = 0; sz = fread(buf, 1, MT, stdin);//一次性输入 } template<class T> inline bool read(T &t){ while( c < sz && buf[c] != '-' && ( buf[c]<'0' || buf[c] >'9')) c++; if( c>=sz) return false; bool flag = 0; if( buf[c]== '-') flag = 1,c++; for( t=0; c<=sz && '0' <=buf[c] && buf[c] <= '9'; c++ ) t= t*10 + buf[c]-'0'; if(flag) t=-t; return true; } } ll inv[maxn*2]; inline void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){ x=1; y=0; d=a; }else{ ex_gcd(b,a%b,d,y,x); y-=x*(a/b);};} inline ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;} inline ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll ans=exgcd(b,a%b,x,y);ll temp=x;x=y;y=temp-a/b*y;return ans;} inline ll lcm(ll a,ll b){ return b/gcd(a,b)*a;} inline ll qpow(ll x,ll n){ll res=1;for(;n;n>>=1){if(n&1)res=(res*x)%MOD;x=(x*x)%MOD;}return res;} inline ll inv_exgcd(ll a,ll n){ll d,x,y;ex_gcd(a,n,d,x,y);return d==1?(x+n)%n:-1;} inline ll inv1(ll b){return b==1?1:(MOD-MOD/b)*inv1(MOD%b)%MOD;} inline ll inv2(ll b){return qpow(b,MOD-2);} struct node{ ll x,y,z; }a[MAXN]; struct EDGE{ ll v,next; ll w; }edge[MAXN]; ll head[MAXN],cot; int st=0,ed=MAXN-5; int vis[MAXN]; void init() { cot=0; mem(head,-1); } void add(ll u,ll v) { edge[++cot].v=v; edge[cot].next=head[u]; head[u]=cot; edge[++cot].v=u; edge[cot].next=head[v]; head[v]=cot; } ll dis(ll x,ll y) { return (pow(a[x].x-a[y].x,2)+pow(a[x].y-a[y].y,2)+pow(a[x].z-a[y].z,2)); } bool SPFA() { mem(vis,0); queue<ll>Q; Q.push(st); vis[st]=1; while(!Q.empty()) { ll u=Q.front(); Q.pop(); // vis[u]=0; for(int i=head[u];i!=-1;i=edge[i].next) { if(!vis[edge[i].v]) { // printf("nest is %d\n",edge[i].v); vis[edge[i].v]=1; Q.push(edge[i].v); } } } } int main() { int T; ll n,h,r; cin>>T; while(T--) { init(); memset(a,0,sizeof(a)); mem(edge,0); scanf("%lld %lld %lld",&n,&h,&r); for(ll i=1;i<=n;i++) { scanf("%lld %lld %lld",&a[i].x,&a[i].y,&a[i].z); } for(ll i=1;i<=n;i++) { if(r>=a[i].z) add(st,i); if(a[i].z+r>=h) add(i,ed); for(ll j=i+1;j<=n;j++) { if(dis(i,j)<= (4*r*r)) { //printf("+++ %lld %lld \n",dis(i,j),2*r); add(i,j); } } } SPFA(); if(vis[ed]) printf("Yes\n"); else printf("No\n"); } return 0; }
并查集
//#include <bits/stdc++.h> #include <iostream> #include <stdio.h> #include <algorithm> #include <cmath> #include <math.h> #include <cstring> #include <string> #include <queue> #include <deque> #include <stack> #include <stdlib.h> #include <list> #include <map> #include <set> #include <bitset> #include <vector> #define mem(a,b) memset(a,b,sizeof(a)) #define findx(x) lower_bound(b+1,b+1+bn,x)-b #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w",stdout) #define S1(n) scanf("%d",&n) #define SL1(n) scanf("%I64d",&n) #define S2(n,m) scanf("%d%d",&n,&m) #define SL2(n,m) scanf("%I64d%I64d",&n,&m) #define Pr(n) printf("%d\n",n) #define lson rt << 1, l, mid #define rson rt << 1|1, mid + 1, r #define FI(n) IO::read(n) #define Be IO::begin() using namespace std; typedef long long ll; const double PI=acos(-1); const int INF=0x3f3f3f3f; const double esp=1e-6; const int maxn=1e5+5; const int MAXN=50005; const int MOD=1e9+7; const int mod=1e9+7; int dir[5][2]={0,1,0,-1,1,0,-1,0}; namespace IO { const int MT = 5e7; char buf[MT]; int c,sz; void begin(){ c = 0; sz = fread(buf, 1, MT, stdin);//一次性输入 } template<class T> inline bool read(T &t){ while( c < sz && buf[c] != '-' && ( buf[c]<'0' || buf[c] >'9')) c++; if( c>=sz) return false; bool flag = 0; if( buf[c]== '-') flag = 1,c++; for( t=0; c<=sz && '0' <=buf[c] && buf[c] <= '9'; c++ ) t= t*10 + buf[c]-'0'; if(flag) t=-t; return true; } } ll inv[maxn*2]; inline void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){ x=1; y=0; d=a; }else{ ex_gcd(b,a%b,d,y,x); y-=x*(a/b);};} inline ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;} inline ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll ans=exgcd(b,a%b,x,y);ll temp=x;x=y;y=temp-a/b*y;return ans;} inline ll lcm(ll a,ll b){ return b/gcd(a,b)*a;} inline ll qpow(ll x,ll n){ll res=1;for(;n;n>>=1){if(n&1)res=(res*x)%MOD;x=(x*x)%MOD;}return res;} inline ll inv_exgcd(ll a,ll n){ll d,x,y;ex_gcd(a,n,d,x,y);return d==1?(x+n)%n:-1;} inline ll inv1(ll b){return b==1?1:(MOD-MOD/b)*inv1(MOD%b)%MOD;} inline ll inv2(ll b){return qpow(b,MOD-2);} int st=0,ed=MAXN-5; ll h,n,r; struct node{ ll x,y,z; }a[MAXN]; ll pre[MAXN]; ll finds(ll x) { return pre[x]==x? x:(pre[x]=finds(pre[x])); } void join(ll x,ll y) { ll fx=finds(x);ll fy=finds(y); //printf("%d is %d | %d is %d\n",x,fx,y,fy); if(fx!=fy) pre[fx]=fy; } void init() { pre[st]=st; pre[ed]=ed; for(ll i=1;i<=n;i++) { pre[i]=i; } } ll dis(int x,int y) { return pow(a[x].x-a[y].x,2)+pow(a[x].y-a[y].y,2)+pow(a[x].z-a[y].z,2); } int main() { int T; cin>>T; while(T--) { scanf("%lld %lld %lld",&n,&h,&r); init(); for(int i=1;i<=n;i++) { scanf("%lld %lld %lld",&a[i].x,&a[i].y,&a[i].z); if(r>=a[i].z) { join(i,st); } if(r+a[i].z>=h) { join(i,ed); } } for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { if(dis(i,j)<=(4*r*r)) { join(i,j); } } } int cot=0; //printf("pres is %d \n",finds(ed)); if(finds(st)==finds(ed) )//|| finds(ed)==st) printf("Yes\n"); else printf("No\n"); } return 0; }
123
岂曰无衣?与子同袍。王于兴师,修我戈矛。与子同仇!
岂曰无衣?与子同泽。王于兴师,修我矛戟。与子偕作!
岂曰无衣?与子同裳。王于兴师,修我甲兵。与子偕行!