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)的距离公式如下:

输入

包含多组数据。 
第一行,包含一个正整数 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

posted @ 2017-11-28 13:13  Sizaif  阅读(229)  评论(0编辑  收藏  举报