洛谷 P3958 [NOIP2017 提高组] 奶酪(建图,dfs)

传送门


解题思路

\(n^2\) 遍历每个点,判断两个空洞之间是否能联通,若联通,则在两个点之间建一条边。
然后在能抵达上表面的点和能抵达下表面的点分别建边连向上表面/下表面,最后dfs判断上下表面是否联通即可。
总复杂度 \(O(n^2)\)

AC代码

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e3+5;
int t,n;
long long h,x[maxn],y[maxn],z[maxn],r;
int cnt,p[maxn],vis[maxn];
struct node{
	int v,next;
}e[maxn*maxn*2];
void insert(int u,int v){
	cnt++;
	e[cnt].v=v;
	e[cnt].next=p[u];
	p[u]=cnt;
} 
inline long long getdis(int i,int j){
	return (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j]);
}
bool dfs(int u){
	if(u==n+1) return 1;
	vis[u]=1;
	for(int i=p[u];i!=-1;i=e[i].next){
		int v=e[i].v;
		if(vis[v]) continue;
		if(dfs(v)) return 1;
	}
	return 0;
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--){
    	cnt=0;
    	memset(vis,0,sizeof(vis));
    	memset(p,-1,sizeof(p));
    	cin>>n>>h>>r;
    	for(int i=1;i<=n;i++) cin>>x[i]>>y[i]>>z[i];
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++){
    			if(getdis(i,j)<=4*r*r){
    				insert(i,j);
    				insert(j,i);
				}
			}
		}
		for(int i=1;i<=n;i++){
			if(z[i]<=r){
				insert(i,n+1);
				insert(n+1,i);
			}
			if(h-z[i]<=r){
				insert(0,i);
				insert(i,0);
			}
		}
		if(dfs(0)) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
    return 0;
}

//NOIP2017提高组Day2 t1

posted @ 2021-08-21 14:07  尹昱钦  阅读(65)  评论(0编辑  收藏  举报